mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-19 16:41:53 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a52783bb1 | ||
|
|
195f1854ec | ||
|
|
2e5596a6e4 | ||
|
|
9fc13c6c45 | ||
|
|
4b4d4e36c7 | ||
|
|
1e7bdc560b | ||
|
|
aff0f8d64c | ||
|
|
7a812d6e6b | ||
|
|
26f2105801 | ||
|
|
feef345a3b | ||
|
|
314ae58ebd | ||
|
|
d8b6232ac1 | ||
|
|
41e22ee64d | ||
|
|
be2fbcd4cb | ||
|
|
14e7f37522 |
@@ -1,5 +1,5 @@
|
|||||||
# ha-bridge
|
# ha-bridge
|
||||||
Emulates Philips Hue api to other home automation gateways such as an Amazon Echo. The Bridge has helpers to build devices for the gateway for the Logitech Harmony Hub, Vera, Vera Lite or Vera Edge. Alternatively the Bridge supports custom calls as well. The Bridge handles basic commands such as "On", "Off" and "brightness" commands of the hue protocol.
|
Emulates Philips Hue api to other home automation gateways such as an Amazon Echo. The Bridge has helpers to build devices for the gateway for the Logitech Harmony Hub, Vera, Vera Lite or Vera Edge. Alternatively the Bridge supports custom calls as well. The Bridge handles basic commands such as "On", "Off" and "brightness" commands of the hue protocol. You can provide multiple harmony hubs for control.
|
||||||
## Build
|
## Build
|
||||||
To customize and build it yourself, build a new jar with maven:
|
To customize and build it yourself, build a new jar with maven:
|
||||||
```
|
```
|
||||||
@@ -22,8 +22,8 @@ The server defaults to running on port 8080. If you're already running a server
|
|||||||
The default location for the db to contain the devices as they are added is "data/devices.db". If you would like a different filename or directory, specify -Dupnp.devices.db=`<directory>/<filename> or <filename>` if it is the same directory.
|
The default location for the db to contain the devices as they are added is "data/devices.db". If you would like a different filename or directory, specify -Dupnp.devices.db=`<directory>/<filename> or <filename>` if it is the same directory.
|
||||||
### -Dupnp.response.port=`<port>`
|
### -Dupnp.response.port=`<port>`
|
||||||
The upnp response port that will be used. The default is 50000.
|
The upnp response port that will be used. The default is 50000.
|
||||||
### -Dharmony.address=`<ip address>`
|
### -Dharmony.address=`<ip address>` | `<{devices:[{name:ahub,ip:x.y.w.z},{name:anotherhub,ip:a.b.c.d}]}>`
|
||||||
The argument for the Harmony Hub address should be given as the system does not have a way to find the address. Supply -Dharmony.address=X.Y.Z.A on the command line to provide it. If a Harmony Hub is not used, do not set it.
|
The argument for the Harmony Hub address should be given as the system does not have a way to find the address. Supply -Dharmony.address=X.Y.Z.A on the command line to provide it. If a Harmony Hub is not used, do not set it. To provide multiple harmony hubs, use the json style notation outlined above to provide the list. This argument is backwards compatible.
|
||||||
### -Dharmony.user=`<username>`
|
### -Dharmony.user=`<username>`
|
||||||
The user name of the MyHarmony.com account for the Harmony Hub. This needs to be given if you are using the Harmony Hub Features, provide -Dharmony.user=`<username>` on the command line.
|
The user name of the MyHarmony.com account for the Harmony Hub. This needs to be given if you are using the Harmony Hub Features, provide -Dharmony.user=`<username>` on the command line.
|
||||||
### -Dharmony.pwd=`<password>`
|
### -Dharmony.pwd=`<password>`
|
||||||
|
|||||||
4
pom.xml
4
pom.xml
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
<groupId>com.bwssystems.HABridge</groupId>
|
<groupId>com.bwssystems.HABridge</groupId>
|
||||||
<artifactId>ha-bridge</artifactId>
|
<artifactId>ha-bridge</artifactId>
|
||||||
<version>1.0.8</version>
|
<version>1.2.0</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>HA Bridge</name>
|
<name>HA Bridge</name>
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
<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>
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
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 String 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;
|
||||||
@@ -43,10 +46,10 @@ public class BridgeSettings {
|
|||||||
public void setVeraAddress(String veraAddress) {
|
public void setVeraAddress(String 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 +64,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;
|
||||||
}
|
}
|
||||||
@@ -85,7 +94,8 @@ public class BridgeSettings {
|
|||||||
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_HARMONY_ADDRESS))
|
||||||
return false;
|
return false;
|
||||||
if(this.harmonypwd == null || this.harmonypwd == "")
|
if(this.harmonypwd == null || this.harmonypwd == "")
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ 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 UPNP_RESPONSE_DEVICES = "30";
|
||||||
public final static String DEFAULT_VERA_ADDRESS = "1.1.1.1";
|
public final static String DEFAULT_VERA_ADDRESS = "1.1.1.1";
|
||||||
public final static String DEFAULT_HARMONY_ADDRESS = "1.1.1.1";
|
public final static String DEFAULT_HARMONY_ADDRESS = "1.1.1.1";
|
||||||
|
public final static String DEFAULT_HARMONY_ADDRESS_LIST = "{devices:[{name:default,ip:1.1.1.1}]}";
|
||||||
public final static String DEFAULT_HARMONY_USER = "";
|
public final static String DEFAULT_HARMONY_USER = "";
|
||||||
public final static String DEFAULT_HARMONY_PWD = "";
|
public final static String DEFAULT_HARMONY_PWD = "";
|
||||||
public final static String DFAULT_WEB_PORT = "8080";
|
public final static String DFAULT_WEB_PORT = "8080";
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ 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.harmony.HarmonyHome;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
public class HABridge {
|
public class HABridge {
|
||||||
|
|
||||||
@@ -34,7 +35,7 @@ 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;
|
||||||
HueMulator theHueMulator;
|
HueMulator theHueMulator;
|
||||||
UpnpSettingsResource theSettingResponder;
|
UpnpSettingsResource theSettingResponder;
|
||||||
UpnpListener theUpnpListener;
|
UpnpListener theUpnpListener;
|
||||||
@@ -61,12 +62,25 @@ public class HABridge {
|
|||||||
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));
|
bridgeSettings.setVeraAddress(System.getProperty("vera.address", Configuration.DEFAULT_VERA_ADDRESS));
|
||||||
bridgeSettings.setHarmonyAddress(System.getProperty("harmony.address", Configuration.DEFAULT_HARMONY_ADDRESS));
|
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_HARMONY_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_HARMONY_USER));
|
bridgeSettings.setHarmonyUser(System.getProperty("harmony.user", Configuration.DEFAULT_HARMONY_USER));
|
||||||
bridgeSettings.setHarmonyPwd(System.getProperty("harmony.pwd", Configuration.DEFAULT_HARMONY_PWD));
|
bridgeSettings.setHarmonyPwd(System.getProperty("harmony.pwd", Configuration.DEFAULT_HARMONY_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)));
|
||||||
|
|
||||||
// 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
|
||||||
@@ -75,16 +89,11 @@ 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);
|
|
||||||
} catch (Exception e) {
|
|
||||||
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);
|
||||||
// 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);
|
||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,9 +14,9 @@ public class HueApiResponse {
|
|||||||
private Map<String, String> groups;
|
private Map<String, String> groups;
|
||||||
private HueConfig config;
|
private HueConfig config;
|
||||||
|
|
||||||
public HueApiResponse(String name, String ipaddress, String username, String userid) {
|
public HueApiResponse(String name, String ipaddress, String devicetype, String userid) {
|
||||||
super();
|
super();
|
||||||
this.setConfig(HueConfig.createConfig(name, ipaddress, username, userid));
|
this.setConfig(HueConfig.createConfig(name, ipaddress, devicetype, userid));
|
||||||
this.setGroups(new HashMap<>());
|
this.setGroups(new HashMap<>());
|
||||||
this.setScenes(new HashMap<>());
|
this.setScenes(new HashMap<>());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,14 @@
|
|||||||
package com.bwssystems.HABridge.api.hue;
|
package com.bwssystems.HABridge.api.hue;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.NetworkInterface;
|
||||||
|
import java.net.SocketException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
public class HueConfig
|
public class HueConfig
|
||||||
{
|
{
|
||||||
@@ -26,10 +33,13 @@ public class HueConfig
|
|||||||
|
|
||||||
public static HueConfig createConfig(String name, String ipaddress, String devicetype, String userid) {
|
public static HueConfig createConfig(String name, String ipaddress, String devicetype, String userid) {
|
||||||
HueConfig aConfig = new HueConfig();
|
HueConfig aConfig = new HueConfig();
|
||||||
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||||
|
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||||
|
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
|
aConfig.setMac(HueConfig.getMacAddress(ipaddress));
|
||||||
aConfig.setApiversion("1.4.0");
|
aConfig.setApiversion("1.4.0");
|
||||||
aConfig.setPortalservices(false);
|
aConfig.setPortalservices(false);
|
||||||
aConfig.setGateway("192.168.1.1");
|
aConfig.setGateway(ipaddress);
|
||||||
aConfig.setMac("00:00:88:00:bb:ee");
|
|
||||||
aConfig.setSwversion("01005215");
|
aConfig.setSwversion("01005215");
|
||||||
aConfig.setLinkbutton(false);
|
aConfig.setLinkbutton(false);
|
||||||
aConfig.setIpaddress(ipaddress);
|
aConfig.setIpaddress(ipaddress);
|
||||||
@@ -38,20 +48,46 @@ public class HueConfig
|
|||||||
aConfig.setNetmask("255.255.255.0");
|
aConfig.setNetmask("255.255.255.0");
|
||||||
aConfig.setName(name);
|
aConfig.setName(name);
|
||||||
aConfig.setDhcp(true);
|
aConfig.setDhcp(true);
|
||||||
aConfig.setUtc("2014-07-17T09:27:35");
|
aConfig.setUtc(dateFormatGmt.format(new Date()));
|
||||||
aConfig.setProxyaddress("0.0.0.0");
|
aConfig.setProxyaddress("none");
|
||||||
aConfig.setLocaltime("2014-07-17T11:27:35");
|
aConfig.setLocaltime(dateFormat.format(new Date()));
|
||||||
aConfig.setTimezone("America/Chicago");
|
aConfig.setTimezone(TimeZone.getDefault().getID());
|
||||||
aConfig.setZigbeechannel("6");
|
aConfig.setZigbeechannel("6");
|
||||||
Map<String, WhitelistEntry> awhitelist = new HashMap<>();
|
Map<String, WhitelistEntry> awhitelist = new HashMap<>();
|
||||||
awhitelist.put(userid, WhitelistEntry.createEntry(devicetype));
|
awhitelist.put(userid, WhitelistEntry.createEntry(devicetype));
|
||||||
aConfig.setWhitelist(awhitelist);
|
aConfig.setWhitelist(awhitelist);
|
||||||
|
|
||||||
|
|
||||||
return aConfig;
|
return aConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String getMacAddress(String addr)
|
||||||
|
{
|
||||||
|
InetAddress ip;
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
try {
|
||||||
|
|
||||||
|
ip = InetAddress.getByName(addr);
|
||||||
|
|
||||||
|
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
|
||||||
|
|
||||||
|
byte[] mac = network.getHardwareAddress();
|
||||||
|
|
||||||
|
for (int i = 0; i < mac.length; i++) {
|
||||||
|
sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? ":" : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
|
||||||
|
sb.append("00:00:88:00:bb:ee");
|
||||||
|
|
||||||
|
} catch (SocketException e){
|
||||||
|
|
||||||
|
sb.append("00:00:88:00:bb:ee");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
public Boolean getPortalservices() {
|
public Boolean getPortalservices() {
|
||||||
return portalservices;
|
return portalservices;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ package com.bwssystems.HABridge.dao;
|
|||||||
public class DeviceDescriptor{
|
public class DeviceDescriptor{
|
||||||
private String id;
|
private String id;
|
||||||
private String name;
|
private String name;
|
||||||
|
private String mapId;
|
||||||
|
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;
|
||||||
@@ -21,7 +24,23 @@ public class DeviceDescriptor{
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDeviceType() {
|
public String getMapId() {
|
||||||
|
return mapId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMapId(String mapId) {
|
||||||
|
this.mapId = mapId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMapType() {
|
||||||
|
return mapType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMapType(String mapType) {
|
||||||
|
this.mapType = mapType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceType() {
|
||||||
return deviceType;
|
return deviceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -178,9 +178,18 @@ public class DeviceRepository {
|
|||||||
} else if (name.equals("name")) {
|
} else if (name.equals("name")) {
|
||||||
deviceEntry.setName(reader.nextString());
|
deviceEntry.setName(reader.nextString());
|
||||||
log.debug("Read a Device - device json name: " + deviceEntry.getName());
|
log.debug("Read a Device - device json name: " + deviceEntry.getName());
|
||||||
|
} else if (name.equals("mapType")) {
|
||||||
|
deviceEntry.setMapType(reader.nextString());
|
||||||
|
log.debug("Read a Device - device json name: " + deviceEntry.getMapType());
|
||||||
|
} else if (name.equals("mapId")) {
|
||||||
|
deviceEntry.setMapId(reader.nextString());
|
||||||
|
log.debug("Read a Device - device json name: " + deviceEntry.getMapId());
|
||||||
} 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());
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import com.bwssystems.HABridge.JsonTransformer;
|
|||||||
import com.bwssystems.HABridge.Version;
|
import com.bwssystems.HABridge.Version;
|
||||||
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.harmony.HarmonyHome;
|
||||||
import com.bwssystems.luupRequests.Sdata;
|
import com.bwssystems.luupRequests.Sdata;
|
||||||
import com.bwssystems.vera.VeraInfo;
|
import com.bwssystems.vera.VeraInfo;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
@@ -35,14 +35,13 @@ public class DeviceResource {
|
|||||||
private DeviceRepository deviceRepository;
|
private DeviceRepository deviceRepository;
|
||||||
private VeraInfo veraInfo;
|
private VeraInfo veraInfo;
|
||||||
private Version version;
|
private Version version;
|
||||||
private HarmonyHandler myHarmonyHandler;
|
private HarmonyHome myHarmonyHome;
|
||||||
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) {
|
||||||
super();
|
|
||||||
this.deviceRepository = new DeviceRepository(theSettings.getUpnpDeviceDb());
|
this.deviceRepository = new DeviceRepository(theSettings.getUpnpDeviceDb());
|
||||||
this.veraInfo = new VeraInfo(theSettings.getVeraAddress(), theSettings.isValidVera());
|
this.veraInfo = new VeraInfo(theSettings.getVeraAddress(), theSettings.isValidVera());
|
||||||
this.myHarmonyHandler = myHarmony;
|
this.myHarmonyHome = theHarmonyHome;
|
||||||
this.version = theVersion;
|
this.version = theVersion;
|
||||||
setupEndpoints();
|
setupEndpoints();
|
||||||
}
|
}
|
||||||
@@ -107,6 +106,9 @@ public class DeviceResource {
|
|||||||
deviceEntry.setName(device.getName());
|
deviceEntry.setName(device.getName());
|
||||||
if (device.getDeviceType() != null)
|
if (device.getDeviceType() != null)
|
||||||
deviceEntry.setDeviceType(device.getDeviceType());
|
deviceEntry.setDeviceType(device.getDeviceType());
|
||||||
|
deviceEntry.setMapId(device.getMapId());
|
||||||
|
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());
|
||||||
@@ -141,8 +143,9 @@ public class DeviceResource {
|
|||||||
}, new JsonTransformer());
|
}, new JsonTransformer());
|
||||||
|
|
||||||
delete (API_CONTEXT + "/:id", "application/json", (request, response) -> {
|
delete (API_CONTEXT + "/:id", "application/json", (request, response) -> {
|
||||||
log.debug("Delete a device");
|
String anId = request.params(":id");
|
||||||
DeviceDescriptor deleted = deviceRepository.findOne(request.params(":id"));
|
log.debug("Delete a device: " + anId);
|
||||||
|
DeviceDescriptor deleted = deviceRepository.findOne(anId);
|
||||||
if(deleted == null)
|
if(deleted == null)
|
||||||
response.status(HttpStatus.SC_NOT_FOUND);
|
response.status(HttpStatus.SC_NOT_FOUND);
|
||||||
else
|
else
|
||||||
@@ -184,32 +187,32 @@ public class DeviceResource {
|
|||||||
|
|
||||||
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());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
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;
|
||||||
@@ -8,6 +9,7 @@ import com.bwssystems.HABridge.api.hue.HueApiResponse;
|
|||||||
import com.bwssystems.HABridge.dao.*;
|
import com.bwssystems.HABridge.dao.*;
|
||||||
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.fasterxml.jackson.databind.DeserializationFeature;
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
@@ -55,17 +57,19 @@ 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 HttpClient httpClient;
|
private HttpClient httpClient;
|
||||||
private ObjectMapper mapper;
|
private ObjectMapper mapper;
|
||||||
|
private BridgeSettings bridgeSettings;
|
||||||
|
|
||||||
|
|
||||||
public HueMulator(DeviceRepository aDeviceRepository, HarmonyHandler theHandler){
|
public HueMulator(BridgeSettings theBridgeSettings, DeviceRepository aDeviceRepository, HarmonyHome theHarmonyHome){
|
||||||
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;
|
myHarmonyHome = theHarmonyHome;
|
||||||
|
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 +78,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 +107,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 +121,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"));
|
||||||
@@ -156,6 +166,31 @@ public class HueMulator {
|
|||||||
return "[{\"success\":{\"username\":\"" + newUser + "\"}}]";
|
return "[{\"success\":{\"username\":\"" + newUser + "\"}}]";
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
// 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) -> {
|
||||||
|
String userId = request.params(":userid");
|
||||||
|
log.debug("hue api config requested: " + userId + " from " + request.ip());
|
||||||
|
HueApiResponse apiResponse = new HueApiResponse("Philips hue", request.ip(), "My App", userId);
|
||||||
|
|
||||||
|
response.type("application/json; charset=utf-8");
|
||||||
|
response.status(HttpStatus.SC_OK);
|
||||||
|
String responseString = null;
|
||||||
|
responseString = "[{\"swversion\":\"" + apiResponse.getConfig().getSwversion() + "\",\"apiversion\":\"" + apiResponse.getConfig().getApiversion() + "\",\"name\":\"" + apiResponse.getConfig().getName() + "\",\"mac\":\"" + apiResponse.getConfig().getMac() + "\"}]";
|
||||||
|
return responseString;
|
||||||
|
});
|
||||||
|
|
||||||
|
// http://ip_address:port/api/{userId}/config returns json objects for the config
|
||||||
|
get(HUE_CONTEXT + "/:userid/config", "application/json", (request, response) -> {
|
||||||
|
String userId = request.params(":userid");
|
||||||
|
log.debug("hue api config requested: " + userId + " from " + request.ip());
|
||||||
|
HueApiResponse apiResponse = new HueApiResponse("Philips hue", request.ip(), "My App", userId);
|
||||||
|
|
||||||
|
response.type("application/json; charset=utf-8");
|
||||||
|
response.status(HttpStatus.SC_OK);
|
||||||
|
return apiResponse.getConfig();
|
||||||
|
}, new JsonTransformer());
|
||||||
|
|
||||||
|
|
||||||
// http://ip_address:port/api/{userId} returns json objects for the full state
|
// http://ip_address:port/api/{userId} returns json objects for the full state
|
||||||
get(HUE_CONTEXT + "/:userid", "application/json", (request, response) -> {
|
get(HUE_CONTEXT + "/:userid", "application/json", (request, response) -> {
|
||||||
String userId = request.params(":userid");
|
String userId = request.params(":userid");
|
||||||
@@ -216,26 +251,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.error("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.error("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();
|
||||||
@@ -259,18 +297,31 @@ public class HueMulator {
|
|||||||
else
|
else
|
||||||
responseString = responseString + "]";
|
responseString = responseString + "]";
|
||||||
|
|
||||||
|
|
||||||
if(device.getDeviceType().toLowerCase().contains("activity"))
|
if(device.getDeviceType().toLowerCase().contains("activity"))
|
||||||
{
|
{
|
||||||
log.debug("executing activity to Harmony: " + url);
|
log.debug("executing 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.error("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"))
|
||||||
{
|
{
|
||||||
log.debug("executing button press to Harmony: " + url);
|
log.debug("executing button press to Harmony: " + url);
|
||||||
ButtonPress aDeviceButton = new Gson().fromJson(url, ButtonPress.class);
|
ButtonPress aDeviceButton = new Gson().fromJson(url, ButtonPress.class);
|
||||||
myHarmony.pressButton(aDeviceButton);
|
HarmonyHandler myHarmony = myHarmonyHome.getHarmonyHandler(device.getTargetDevice());
|
||||||
|
if(myHarmony == null)
|
||||||
|
{
|
||||||
|
log.error("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.pressButton(aDeviceButton);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -284,15 +335,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.error("Error on calling url to change device state: " + url);
|
log.error("Error on calling url to change device state: " + url);
|
||||||
return null;
|
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + ",\"description\": \"Error on calling url to change device state\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,14 +76,7 @@ public class UpnpListener {
|
|||||||
byte[] buf = new byte[1024];
|
byte[] buf = new byte[1024];
|
||||||
DatagramPacket packet = new DatagramPacket(buf, buf.length);
|
DatagramPacket packet = new DatagramPacket(buf, buf.length);
|
||||||
upnpMulticastSocket.receive(packet);
|
upnpMulticastSocket.receive(packet);
|
||||||
String packetString = new String(packet.getData());
|
if(isSSDPDiscovery(packet)){
|
||||||
if(packetString != null && packetString.contains("M-SEARCH")) {
|
|
||||||
if(traceupnp)
|
|
||||||
log.info("Traceupnp: SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString);
|
|
||||||
else
|
|
||||||
log.debug("Got SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString);
|
|
||||||
}
|
|
||||||
if(isSSDPDiscovery(packetString)){
|
|
||||||
sendUpnpResponse(responseSocket, packet.getAddress(), packet.getPort());
|
sendUpnpResponse(responseSocket, packet.getAddress(), packet.getPort());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,17 +90,22 @@ public class UpnpListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* very naive ssdp discovery packet detection
|
* ssdp discovery packet detection
|
||||||
* @param body
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
protected boolean isSSDPDiscovery(String body){
|
protected boolean isSSDPDiscovery(DatagramPacket packet){
|
||||||
// log.debug("Check if this is a MAN ssdp-discover packet for a upnp basic device: " + body);
|
//Only respond to discover request for strict upnp form
|
||||||
//Only respond to discover request for upnp basic device from echo, the others are for the wemo
|
String packetString = new String(packet.getData());
|
||||||
if(body != null && body.contains("M-SEARCH") && body.contains("\"ssdp:discover\"")){
|
if(packetString != null && packetString.startsWith("M-SEARCH * HTTP/1.1") && packetString.contains("\"ssdp:discover\"")){
|
||||||
if(traceupnp)
|
if(traceupnp) {
|
||||||
|
log.info("Traceupnp: SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString);
|
||||||
log.info("Traceupnp: isSSDPDiscovery found message to be an M-SEARCH message.");
|
log.info("Traceupnp: isSSDPDiscovery found message to be an M-SEARCH message.");
|
||||||
if(strict && body.startsWith("M-SEARCH * HTTP/1.1") && body.contains("MAN: \"ssdp:discover\"") && (body.contains("ST: urn:schemas-upnp-org:device:basic:1") || body.contains("ST: upnp:rootdevice") || body.contains("ST: ssdp:all")))
|
}
|
||||||
|
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(traceupnp)
|
if(traceupnp)
|
||||||
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);
|
||||||
@@ -134,7 +132,7 @@ public class UpnpListener {
|
|||||||
"USN: uuid:Socket-1_0-221438K0100073::urn:schemas-upnp-org:device:basic:1\r\n\r\n";
|
"USN: uuid:Socket-1_0-221438K0100073::urn:schemas-upnp-org:device:basic:1\r\n\r\n";
|
||||||
protected void sendUpnpResponse(DatagramSocket socket, InetAddress requester, int sourcePort) throws IOException {
|
protected void sendUpnpResponse(DatagramSocket socket, InetAddress requester, int sourcePort) throws IOException {
|
||||||
String discoveryResponse = null;
|
String discoveryResponse = null;
|
||||||
discoveryResponse = String.format(discoveryTemplate, responseAddress, httpServerPort, getRandomUUIDString());
|
discoveryResponse = String.format(discoveryTemplate, responseAddress, httpServerPort);
|
||||||
if(traceupnp)
|
if(traceupnp)
|
||||||
log.info("Traceupnp: sendUpnpResponse: " + discoveryResponse);
|
log.info("Traceupnp: sendUpnpResponse: " + discoveryResponse);
|
||||||
else
|
else
|
||||||
@@ -142,8 +140,4 @@ public class UpnpListener {
|
|||||||
DatagramPacket response = new DatagramPacket(discoveryResponse.getBytes(), discoveryResponse.length(), requester, sourcePort);
|
DatagramPacket response = new DatagramPacket(discoveryResponse.getBytes(), discoveryResponse.length(), requester, sourcePort);
|
||||||
socket.send(response);
|
socket.send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getRandomUUIDString(){
|
|
||||||
return "88f6698f-2c83-4393-bd03-cd54a9f8595"; // https://xkcd.com/221/
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
102
src/main/java/com/bwssystems/harmony/HarmonyHome.java
Normal file
102
src/main/java/com/bwssystems/harmony/HarmonyHome.java
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
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.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>();
|
||||||
|
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()) {
|
||||||
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);
|
||||||
@@ -54,7 +57,7 @@ public class HarmonyServer {
|
|||||||
log.debug("something is very wrong as dummyProvider is not null...");
|
log.debug("something is very wrong as dummyProvider is not null...");
|
||||||
if(mySettings.isDevMode())
|
if(mySettings.isDevMode())
|
||||||
modeString = " (development mode)";
|
modeString = " (development mode)";
|
||||||
if(noopCalls)
|
else if(noopCalls)
|
||||||
modeString = " (no op calls to harmony)";
|
modeString = " (no op calls to harmony)";
|
||||||
log.info("setup initiated " + modeString + "....");
|
log.info("setup initiated " + modeString + "....");
|
||||||
if(mySettings.isDevMode())
|
if(mySettings.isDevMode())
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public class VeraInfo {
|
|||||||
|
|
||||||
public VeraInfo(String addressString, Boolean isValidVera) {
|
public VeraInfo(String addressString, Boolean isValidVera) {
|
||||||
super();
|
super();
|
||||||
httpClient = HttpClients.createMinimal();
|
httpClient = HttpClients.createDefault();
|
||||||
veraAddressString = addressString;
|
veraAddressString = addressString;
|
||||||
validVera = isValidVera;
|
validVera = isValidVera;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -4,9 +4,6 @@ var app = angular.module('habridge', [
|
|||||||
|
|
||||||
app.config(function ($routeProvider) {
|
app.config(function ($routeProvider) {
|
||||||
$routeProvider.when('/#', {
|
$routeProvider.when('/#', {
|
||||||
templateUrl: 'views/nonconfiguration.html',
|
|
||||||
controller: 'ViewingController'
|
|
||||||
}).when('/show', {
|
|
||||||
templateUrl: 'views/configuration.html',
|
templateUrl: 'views/configuration.html',
|
||||||
controller: 'ViewingController'
|
controller: 'ViewingController'
|
||||||
}).when('/editor', {
|
}).when('/editor', {
|
||||||
@@ -28,7 +25,7 @@ app.config(function ($routeProvider) {
|
|||||||
templateUrl: 'views/harmonyactivity.html',
|
templateUrl: 'views/harmonyactivity.html',
|
||||||
controller: 'AddingController'
|
controller: 'AddingController'
|
||||||
}).otherwise({
|
}).otherwise({
|
||||||
templateUrl: 'views/nonconfiguration.html',
|
templateUrl: 'views/configuration.html',
|
||||||
controller: 'ViewingController'
|
controller: 'ViewingController'
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@@ -249,22 +246,33 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.addDevice = function (id, name, type, onUrl, offUrl, httpVerb, contentType, contentBody, contentBodyOff) {
|
this.findDeviceByMapId = function(id, target, type) {
|
||||||
|
for(var i = 0; i < this.state.devices.length; i++) {
|
||||||
|
if(this.state.devices[i].mapId == id && this.state.devices[i].mapType == type && this.state.devices[i].targetDevice == target)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.addDevice = function (device) {
|
||||||
this.state.error = "";
|
this.state.error = "";
|
||||||
if(httpVerb != null && httpVerb != "")
|
if(device.httpVerb != null && device.httpVerb != "")
|
||||||
type = "custom";
|
device.deviceType = "custom";
|
||||||
if (id) {
|
if (device.id) {
|
||||||
var putUrl = this.state.base + "/" + id;
|
var putUrl = this.state.base + "/" + device.id;
|
||||||
return $http.put(putUrl, {
|
return $http.put(putUrl, {
|
||||||
id: id,
|
id: device.id,
|
||||||
name: name,
|
name: device.name,
|
||||||
deviceType: type,
|
mapId: device.mapId,
|
||||||
onUrl: onUrl,
|
mapType: device.mapType,
|
||||||
offUrl: offUrl,
|
deviceType: device.deviceType,
|
||||||
httpVerb: httpVerb,
|
targetDevice: device.targetDevice,
|
||||||
contentType: contentType,
|
onUrl: device.onUrl,
|
||||||
contentBody: contentBody,
|
offUrl: device.offUrl,
|
||||||
contentBodyOff: contentBodyOff
|
httpVerb: device.httpVerb,
|
||||||
|
contentType: device.contentType,
|
||||||
|
contentBody: device.contentBody,
|
||||||
|
contentBodyOff: device.contentBodyOff
|
||||||
}).then(
|
}).then(
|
||||||
function (response) {
|
function (response) {
|
||||||
self.viewDevices();
|
self.viewDevices();
|
||||||
@@ -277,19 +285,22 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if(type == null || type == "")
|
if(device.deviceType == null || device.deviceType == "")
|
||||||
type = "switch";
|
device.deviceType = "switch";
|
||||||
if(httpVerb != null && httpVerb != "")
|
if(device.httpVerb != null && device.httpVerb != "")
|
||||||
type = "custom";
|
device.deviceType = "custom";
|
||||||
return $http.post(this.state.base, {
|
return $http.post(this.state.base, {
|
||||||
name: name,
|
name: device.name,
|
||||||
deviceType: type,
|
mapId: device.mapId,
|
||||||
onUrl: onUrl,
|
mapType: device.mapType,
|
||||||
offUrl: offUrl,
|
deviceType: device.deviceType,
|
||||||
httpVerb: httpVerb,
|
targetDevice: device.targetDevice,
|
||||||
contentType: contentType,
|
onUrl: device.onUrl,
|
||||||
contentBody: contentBody,
|
offUrl: device.offUrl,
|
||||||
contentBodyOff: contentBodyOff
|
httpVerb: device.httpVerb,
|
||||||
|
contentType: device.contentType,
|
||||||
|
contentBody: device.contentBody,
|
||||||
|
contentBodyOff: device.contentBodyOff
|
||||||
}).then(
|
}).then(
|
||||||
function (response) {
|
function (response) {
|
||||||
self.viewDevices();
|
self.viewDevices();
|
||||||
@@ -319,8 +330,40 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.editDevice = function (id, name, onUrl, offUrl, httpVerb, contentType, contentBody, contentBodyOff) {
|
this.deleteDeviceByMapId = function (id, type) {
|
||||||
self.state.device = {id: id, name: name, onUrl: onUrl, offUrl: offUrl, httpVerb: httpVerb, contentType: contentType, contentBody: contentBody, contentBodyOff: contentBodyOff};
|
for(var i = 0; i < this.state.devices.length; i++) {
|
||||||
|
if(this.state.devices[i].mapId == id && this.state.devices[i].mapType == type)
|
||||||
|
return self.deleteDevice(this.state.devices[i].id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.editDevice = function (device) {
|
||||||
|
self.state.device = device;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.testUrl = function (device, type) {
|
||||||
|
if(type == "on") {
|
||||||
|
$http.put(this.state.huebase + "/test/lights/" + device.id + "/state", "{\"on\":true}").then(
|
||||||
|
function (response) {
|
||||||
|
$window.alert("Request Exceuted: " + response.statusText);
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
$window.alert("Request Error: " + error.statusText + ", with status: " + error.status + ", Pleae look in your console log.");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$http.put(this.state.huebase + "/test/lights/" + device.id + "/state", "{\"on\":false}").then(
|
||||||
|
function (response) {
|
||||||
|
$window.alert("Request Exceuted: " + response.statusText);
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
$window.alert("Request Error: " + error.statusText + ", with status: " + error.status + ", Pleae look in your console log.");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -331,6 +374,8 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
|
|||||||
$scope.bridge = bridgeService.state;
|
$scope.bridge = bridgeService.state;
|
||||||
bridgeService.updateShowVera();
|
bridgeService.updateShowVera();
|
||||||
bridgeService.updateShowHarmony();
|
bridgeService.updateShowHarmony();
|
||||||
|
$scope.visible = false;
|
||||||
|
$scope.imgUrl = "glyphicon glyphicon-plus";
|
||||||
$scope.predicate = '';
|
$scope.predicate = '';
|
||||||
$scope.reverse = true;
|
$scope.reverse = true;
|
||||||
$scope.order = function(predicate) {
|
$scope.order = function(predicate) {
|
||||||
@@ -341,83 +386,26 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
|
|||||||
bridgeService.deleteDevice(device.id);
|
bridgeService.deleteDevice(device.id);
|
||||||
};
|
};
|
||||||
$scope.testUrl = function (device, type) {
|
$scope.testUrl = function (device, type) {
|
||||||
if(type == "on") {
|
bridgeService.testUrl(device, type);
|
||||||
if(device.deviceType == "activity" || device.deviceType == "button") {
|
|
||||||
$http.put($scope.bridge.huebase + "/test/lights/" + device.id + "/state", "{\"on\":true}").then(
|
|
||||||
function (response) {
|
|
||||||
$window.alert("Request Exceuted: " + response.statusText);
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
$window.alert("Request Error: " + error.data.message);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(device.httpVerb == "PUT")
|
|
||||||
$http.put(device.onUrl, device.contentBody).then(
|
|
||||||
function (response) {
|
|
||||||
$window.alert("Request Exceuted: " + response.statusText);
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
$window.alert("Request Error: " + error.data.message);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
else if(device.httpVerb == "POST")
|
|
||||||
$http.post(device.onUrl, device.contentBody).then(
|
|
||||||
function (response) {
|
|
||||||
$window.alert("Request Exceuted: " + response.statusText);
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
$window.alert("Request Error: " + error.data.message);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
else
|
|
||||||
window.open(device.onUrl, "_blank");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(device.deviceType == "activity" || device.deviceType == "button") {
|
|
||||||
$http.put($scope.bridge.huebase + "/test/lights/" + device.id + "/state", "{\"on\":false}").then(
|
|
||||||
function (response) {
|
|
||||||
$window.alert("Request Exceuted: " + response.statusText);
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
$window.alert("Request Error: " + error.data.message);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(device.httpVerb == "PUT")
|
|
||||||
$http.put(device.offUrl, device.contentBodyOff).then(
|
|
||||||
function (response) {
|
|
||||||
$window.alert("Request Exceuted: " + response.statusText);
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
$window.alert("Request Error: " + error.data.message);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
else if(device.httpVerb == "POST")
|
|
||||||
$http.post(device.offUrl, device.contentBody).then(
|
|
||||||
function (response) {
|
|
||||||
$window.alert("Request Exceuted: " + response.statusText);
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
$window.alert("Request Error: " + error.data.message);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
else
|
|
||||||
window.open(device.offUrl, "_blank");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
$scope.setBridgeUrl = function (url) {
|
$scope.setBridgeUrl = function (url) {
|
||||||
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.id, device.name, device.onUrl, device.offUrl, device.httpVerb, device.contentType, device.contentBody, device.contentBodyOff);
|
bridgeService.editDevice(device);
|
||||||
$location.path('/editdevice');
|
$location.path('/editdevice');
|
||||||
};
|
};
|
||||||
|
$scope.toggle = function () {
|
||||||
|
$scope.visible = !$scope.visible;
|
||||||
|
if($scope.visible)
|
||||||
|
$scope.imgUrl = "glyphicon glyphicon-minus";
|
||||||
|
else
|
||||||
|
$scope.imgUrl = "glyphicon glyphicon-plus";
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
app.controller('AddingController', function ($scope, $location, $http, bridgeService, BridgeSettings) {
|
app.controller('AddingController', function ($scope, $location, $http, bridgeService, BridgeSettings) {
|
||||||
@@ -434,6 +422,14 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
|
|||||||
bridgeService.updateShowVera();
|
bridgeService.updateShowVera();
|
||||||
bridgeService.updateShowHarmony();
|
bridgeService.updateShowHarmony();
|
||||||
$scope.device = bridgeService.state.device;
|
$scope.device = bridgeService.state.device;
|
||||||
|
$scope.activitiesVisible = false;
|
||||||
|
$scope.imgButtonsUrl = "glyphicon glyphicon-plus";
|
||||||
|
$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.device_dim_control = "";
|
||||||
@@ -446,6 +442,9 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
|
|||||||
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.mapType = "veraDevice";
|
||||||
|
$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)
|
||||||
$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&DeviceNum="
|
+ "/data_request?id=action&output_format=json&DeviceNum="
|
||||||
@@ -466,6 +465,8 @@ 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.mapType = "veraScene";
|
||||||
|
$scope.device.mapId = $scope.vera.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="
|
||||||
+ $scope.vera.id;
|
+ $scope.vera.id;
|
||||||
@@ -480,6 +481,8 @@ 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.mapType = "veraDevice";
|
||||||
|
$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)
|
||||||
$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&DeviceNum="
|
+ "/data_request?id=action&output_format=json&DeviceNum="
|
||||||
@@ -501,6 +504,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.device.mapType = "veraScene";
|
||||||
|
$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="
|
||||||
+ verascene.id;
|
+ verascene.id;
|
||||||
@@ -511,96 +516,38 @@ 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.onUrl = "{\"name\":\"" + harmonyactivity.id + "\"}";
|
$scope.device.name = harmonyactivity.activity.label;
|
||||||
|
$scope.device.mapType = "harmonyActivity";
|
||||||
|
$scope.device.mapId = harmonyactivity.activity.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";
|
$scope.device.deviceType = "button";
|
||||||
$scope.device.name = harmonydevice.label;
|
$scope.device.targetDevice = harmonydevice.hub;
|
||||||
$scope.device.onUrl = "{\"device\":\"" + harmonydevice.id + "\",\"button\":\"" + onbutton + "\"}";
|
$scope.device.name = harmonydevice.device.label;
|
||||||
$scope.device.offUrl = "{\"device\":\"" + harmonydevice.id + "\",\"button\":\"" + offbutton + "\"}";
|
$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.testUrl = function (device, type) {
|
$scope.testUrl = function (device, type) {
|
||||||
if(type == "on") {
|
bridgeService.testUrl(device, type);
|
||||||
if(device.deviceType == "activity" || device.deviceType == "button") {
|
|
||||||
$http.put($scope.bridge.huebase + "/test/lights/" + device.id + "/state", "{\"on\":true}").then(
|
|
||||||
function (response) {
|
|
||||||
$window.alert("Request Exceuted: " + response.statusText);
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
$window.alert("Request Error: " + error.data.message);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(device.httpVerb == "PUT")
|
|
||||||
$http.put(device.onUrl, device.contentBody).then(
|
|
||||||
function (response) {
|
|
||||||
$window.alert("Request Exceuted: " + response.statusText);
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
$window.alert("Request Error: " + error.data.message);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
else if(device.httpVerb == "POST")
|
|
||||||
$http.post(device.onUrl, device.contentBody).then(
|
|
||||||
function (response) {
|
|
||||||
$window.alert("Request Exceuted: " + response.statusText);
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
$window.alert("Request Error: " + error.data.message);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
else
|
|
||||||
window.open(device.onUrl, "_blank");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(device.deviceType == "activity" || device.deviceType == "button") {
|
|
||||||
$http.put($scope.bridge.huebase + "/test/lights/" + device.id + "/state", "{\"on\":false}").then(
|
|
||||||
function (response) {
|
|
||||||
$window.alert("Request Exceuted: " + response.statusText);
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
$window.alert("Request Error: " + error.data.message);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(device.httpVerb == "PUT")
|
|
||||||
$http.put(device.offUrl, device.contentBodyOff).then(
|
|
||||||
function (response) {
|
|
||||||
$window.alert("Request Exceuted: " + response.statusText);
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
$window.alert("Request Error: " + error.data.message);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
else if(device.httpVerb == "POST")
|
|
||||||
$http.post(device.offUrl, device.contentBody).then(
|
|
||||||
function (response) {
|
|
||||||
$window.alert("Request Exceuted: " + response.statusText);
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
$window.alert("Request Error: " + error.data.message);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
else
|
|
||||||
window.open(device.offUrl, "_blank");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.addDevice = function () {
|
$scope.addDevice = function () {
|
||||||
bridgeService.addDevice($scope.device.id, $scope.device.name, $scope.device.deviceType, $scope.device.onUrl, $scope.device.offUrl, $scope.device.httpVerb, $scope.device.contentType, $scope.device.contentBody, $scope.device.contentBodyOff).then(
|
bridgeService.addDevice($scope.device).then(
|
||||||
function () {
|
function () {
|
||||||
$scope.device.id = "";
|
$scope.device.id = "";
|
||||||
|
$scope.device.mapType = null;
|
||||||
|
$scope.device.mapId = null;
|
||||||
$scope.device.name = "";
|
$scope.device.name = "";
|
||||||
$scope.device.onUrl = "";
|
$scope.device.onUrl = "";
|
||||||
$scope.device.deviceType = "switch";
|
$scope.device.deviceType = "switch";
|
||||||
|
$scope.device.targetDevice = null;
|
||||||
$scope.device.offUrl = "";
|
$scope.device.offUrl = "";
|
||||||
$scope.device.httpVerb = null;
|
$scope.device.httpVerb = null;
|
||||||
$scope.device.contentType = null;
|
$scope.device.contentType = null;
|
||||||
@@ -613,8 +560,143 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$scope.toggleActivities = function () {
|
||||||
|
$scope.activitiesVisible = !$scope.activitiesVisible;
|
||||||
|
if($scope.activitiesVisible)
|
||||||
|
$scope.imgActivitiesUrl = "glyphicon glyphicon-minus";
|
||||||
|
else
|
||||||
|
$scope.imgActivitiesUrl = "glyphicon glyphicon-plus";
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.toggleButtons = function () {
|
||||||
|
$scope.buttonsVisible = !$scope.buttonsVisible;
|
||||||
|
if($scope.buttonsVisible)
|
||||||
|
$scope.imgButtonsUrl = "glyphicon glyphicon-minus";
|
||||||
|
else
|
||||||
|
$scope.imgButtonsUrl = "glyphicon glyphicon-plus";
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.toggleDevices = function () {
|
||||||
|
$scope.devicesVisible = !$scope.devicesVisible;
|
||||||
|
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, mapType) {
|
||||||
|
bridgeService.deleteDeviceByMapId(id, mapType);
|
||||||
|
};
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.filter('availableHarmonyActivityId', 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].activity.id, input[i].hub, "harmonyActivity")){
|
||||||
|
out.push(input[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.filter('unavailableHarmonyActivityId', 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].activity.id, input[i].hub, "harmonyActivity")){
|
||||||
|
out.push(input[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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, "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, "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, "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, "veraScene")){
|
||||||
|
out.push(input[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.filter('configuredButtons', function() {
|
||||||
|
return function(input) {
|
||||||
|
var out = [];
|
||||||
|
if(input == null)
|
||||||
|
return out;
|
||||||
|
for (var i = 0; i < input.length; i++) {
|
||||||
|
if(input[i].mapType == "harmonyButton"){
|
||||||
|
out.push(input[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
app.controller('ErrorsController', function ($scope, bridgeService) {
|
app.controller('ErrorsController', function ($scope, bridgeService) {
|
||||||
$scope.bridge = bridgeService.state;
|
$scope.bridge = bridgeService.state;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -37,6 +37,9 @@
|
|||||||
<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>
|
||||||
@@ -44,6 +47,7 @@
|
|||||||
<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,14 +64,13 @@
|
|||||||
|
|
||||||
<div class="panel panel-default bridgeServer">
|
<div class="panel panel-default bridgeServer">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<a href="#/"><span class="glyphicon glyphicon-minus" aria-hidden="true"></span></a>
|
<h1 class="panel-title">Bridge settings <a ng-click="toggle()"><span class={{imgUrl}} aria-hidden="true"></a></h1>
|
||||||
<h1 class="panel-title">Bridge settings</h1>
|
|
||||||
</div>
|
</div>
|
||||||
<div 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">
|
||||||
@@ -77,7 +80,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">
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<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 new device</h2>
|
<h2 class="panel-title">Edit a device</h2>
|
||||||
</div>
|
</div>
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
@@ -26,6 +26,40 @@
|
|||||||
<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">
|
||||||
Update Device</button>
|
Update Device</button>
|
||||||
</div>
|
</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>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="row">
|
||||||
|
<label class="col-xs-12 col-sm-2 control-label" for="device-map-type">Map Type
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="col-xs-8 col-sm-7">
|
||||||
|
<select name="device-map-type" id="device-map-type" ng-model="device.mapType">
|
||||||
|
<option value="">---Please select---</option> <!-- not selected / blank option -->
|
||||||
|
<option value="veraDevice">Vera Device</option>
|
||||||
|
<option value="veraScene">Vera Scene</option>
|
||||||
|
<option value="harmonyActivity">Harmony Activity</option>
|
||||||
|
<option value="harmonyButton">Harmony Button</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ng-if="device.mapType" class="form-group">
|
||||||
|
<label class="col-xs-12 col-sm-2 control-label" for="device-map-id">Map ID
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="col-xs-8 col-sm-7">
|
||||||
|
<input type="text" class="form-control" id="device-map-id"
|
||||||
|
ng-model="device.mapId" placeholder="1111">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<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-on-url">On
|
<label class="col-xs-12 col-sm-2 control-label" for="device-on-url">On
|
||||||
@@ -35,9 +69,6 @@
|
|||||||
<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>
|
||||||
<div class="clearfix visible-xs"></div>
|
|
||||||
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
|
|
||||||
ng-click="testUrl(device, 'on')">Test</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@@ -49,9 +80,6 @@
|
|||||||
<textarea rows="3" class="form-control" id="device-off-url"
|
<textarea rows="3" class="form-control" id="device-off-url"
|
||||||
ng-model="device.offUrl" placeholder="URL to turn device off"></textarea>
|
ng-model="device.offUrl" placeholder="URL to turn device off"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="clearfix visible-xs"></div>
|
|
||||||
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
|
|
||||||
ng-click="testUrl(device, 'off')">Test</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@@ -69,7 +97,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div ng-if="device.httpVerb" class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label class="col-xs-12 col-sm-2 control-label" for="device-content-type">Content Type
|
<label class="col-xs-12 col-sm-2 control-label" for="device-content-type">Content Type
|
||||||
</label>
|
</label>
|
||||||
@@ -94,7 +122,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div ng-if="device.httpVerb" class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label class="col-xs-12 col-sm-2 control-label"
|
<label class="col-xs-12 col-sm-2 control-label"
|
||||||
for="device-content-body">Content Body On</label>
|
for="device-content-body">Content Body On</label>
|
||||||
@@ -106,7 +134,7 @@
|
|||||||
<div class="clearfix visible-xs"></div>
|
<div class="clearfix visible-xs"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div ng-if="device.httpVerb" class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label class="col-xs-12 col-sm-2 control-label"
|
<label class="col-xs-12 col-sm-2 control-label"
|
||||||
for="device-content-body-off">Content Body Off</label>
|
for="device-content-body-off">Content Body Off</label>
|
||||||
|
|||||||
@@ -98,9 +98,6 @@
|
|||||||
<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>
|
||||||
<div class="clearfix visible-xs"></div>
|
|
||||||
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
|
|
||||||
ng-click="testUrl(device, 'on')">Test</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@@ -112,9 +109,6 @@
|
|||||||
<textarea rows="3" class="form-control" id="device-off-url"
|
<textarea rows="3" class="form-control" id="device-off-url"
|
||||||
ng-model="device.offUrl" placeholder="URL to turn device off"></textarea>
|
ng-model="device.offUrl" placeholder="URL to turn device off"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="clearfix visible-xs"></div>
|
|
||||||
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
|
|
||||||
ng-click="testUrl(device, 'off')">Test</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@@ -132,7 +126,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div ng-if="device.httpVerb" class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label class="col-xs-12 col-sm-2 control-label" for="device-content-type">Content Type
|
<label class="col-xs-12 col-sm-2 control-label" for="device-content-type">Content Type
|
||||||
</label>
|
</label>
|
||||||
@@ -157,7 +151,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div ng-if="device.httpVerb" class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label class="col-xs-12 col-sm-2 control-label"
|
<label class="col-xs-12 col-sm-2 control-label"
|
||||||
for="device-content-body">Content Body On</label>
|
for="device-content-body">Content Body On</label>
|
||||||
@@ -169,7 +163,7 @@
|
|||||||
<div class="clearfix visible-xs"></div>
|
<div class="clearfix visible-xs"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div ng-if="device.httpVerb" class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label class="col-xs-12 col-sm-2 control-label"
|
<label class="col-xs-12 col-sm-2 control-label"
|
||||||
for="device-content-body-off">Content Body Off</label>
|
for="device-content-body-off">Content Body Off</label>
|
||||||
|
|||||||
@@ -26,13 +26,18 @@
|
|||||||
<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 | orderBy:predicate:reverse">
|
<tr ng-repeat="harmonyactivity in bridge.harmonyactivities | availableHarmonyActivityId | orderBy:predicate:reverse">
|
||||||
<td>{{harmonyactivity.label}}</td>
|
<td>{{harmonyactivity.activity.label}}</td>
|
||||||
<td>{{harmonyactivity.id}}</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
|
||||||
@@ -42,6 +47,39 @@
|
|||||||
</table>
|
</table>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h2 class="panel-title">Already Configured Activities <a ng-click="toggleActivities()"><span class={{imgActivitiesUrl}} aria-hidden="true"></a></h2>
|
||||||
|
</div>
|
||||||
|
<ul ng-if="activitiesVisible" class="list-group">
|
||||||
|
<li class="list-group-item">
|
||||||
|
<table class="table table-bordered table-striped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<a href="" ng-click="order('label')">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('hub')">Hub</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'hub'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tr ng-repeat="harmonyactivity in bridge.harmonyactivities | unavailableHarmonyActivityId | orderBy:predicate:reverse">
|
||||||
|
<td>{{harmonyactivity.activity.label}}</td>
|
||||||
|
<td>{{harmonyactivity.activity.id}}</td>
|
||||||
|
<td>{{harmonyactivity.hub}}</td>
|
||||||
|
<td><button class="btn btn-danger" type="submit"
|
||||||
|
ng-click="deleteDeviceByMapId(harmonyactivity.activity.id, 'harmonyActivity')">Delete</button></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</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">
|
||||||
|
|||||||
@@ -26,6 +26,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,18 +37,19 @@
|
|||||||
</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>{{harmonydevice.device.label}}</td>
|
||||||
<td>{{harmonydevice.id}}</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">{{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">{{funcoff.name}}</option>
|
||||||
</optgroup >
|
</optgroup >
|
||||||
</select>
|
</select>
|
||||||
@@ -58,6 +63,46 @@
|
|||||||
</table>
|
</table>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h2 class="panel-title">Already Configured Harmony Buttons <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>
|
||||||
|
<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')">Device Id</a>
|
||||||
|
<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>
|
||||||
|
<a href="" ng-click="order('mapId')">Harmony Device-Button On-Button Off</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'id'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tr ng-repeat="device in bridge.devices | configuredButtons | orderBy:predicate:reverse">
|
||||||
|
<td>{{device.name}}</td>
|
||||||
|
<td>{{device.id}}</td>
|
||||||
|
<td>{{device.targetDevice}}</td>
|
||||||
|
<td>{{device.mapId}}</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-danger" type="submit"
|
||||||
|
ng-click="deleteDeviceByMapId(device.mapId, device.mapType)">Delete</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</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">
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
<ul class="nav nav-pills" role="tablist">
|
|
||||||
<li role="presentation" class="active"><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"><a href="#/editor">Manual Add</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<div ng-controller="ErrorsController">
|
|
||||||
<div ng-if="bridge.error"
|
|
||||||
class="alert alert-warning alert-dismissible" role="alert">
|
|
||||||
<button type="button" class="close" data-dismiss="alert"
|
|
||||||
aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<h2 ng-show='bridge.error != ""'>ERROR</h2>
|
|
||||||
|
|
||||||
<div ng-show='bridge.error != ""'>{{bridge.error}}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<div class="panel-heading">
|
|
||||||
<h2 class="panel-title">Current devices</h2>
|
|
||||||
</div>
|
|
||||||
<table class="table table-bordered table-striped table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<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('name')">Name</a>
|
|
||||||
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span></th>
|
|
||||||
<th>
|
|
||||||
<a href="" ng-click="order('deviceType')">Type</a>
|
|
||||||
<span class="sortorder" ng-show="predicate === 'deviceType'" ng-class="{reverse:reverse}"></span></th>
|
|
||||||
<th>Actions</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tr ng-repeat="device in bridge.devices | orderBy:predicate:reverse">
|
|
||||||
<td>{{device.id}}</td>
|
|
||||||
<td>{{device.name}}</td>
|
|
||||||
<td>{{device.deviceType}}</td>
|
|
||||||
<td>
|
|
||||||
<button class="btn btn-info" type="submit"
|
|
||||||
ng-click="testUrl(device, 'on')">Test ON</button>
|
|
||||||
<button class="btn btn-info" type="submit"
|
|
||||||
ng-click="testUrl(device, 'off')">Test OFF</button>
|
|
||||||
<button class="btn btn-warning" type="submit"
|
|
||||||
ng-click="editDevice(device)">Edit</button>
|
|
||||||
<button class="btn btn-danger" type="submit"
|
|
||||||
ng-click="deleteDevice(device)">Delete</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="panel panel-default bridgeServer">
|
|
||||||
<div class="panel-heading">
|
|
||||||
<a href="#/show"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></a>
|
|
||||||
<h1 class="panel-title">Bridge settings</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tr ng-repeat="veradevice in bridge.veradevices | orderBy:predicate:reverse">
|
<tr ng-repeat="veradevice in bridge.veradevices | availableVeraDeviceId | orderBy:predicate:reverse">
|
||||||
<td>{{veradevice.name}}</td>
|
<td>{{veradevice.name}}</td>
|
||||||
<td>{{veradevice.id}}</td>
|
<td>{{veradevice.id}}</td>
|
||||||
<td>{{veradevice.category}}</td>
|
<td>{{veradevice.category}}</td>
|
||||||
@@ -59,6 +59,46 @@
|
|||||||
</table>
|
</table>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h2 class="panel-title">Already Configured Vera Devices <a ng-click="toggleDevices()"><span class={{imgDevicesUrl}} aria-hidden="true"></a></h2>
|
||||||
|
</div>
|
||||||
|
<ul ng-if="devicesVisible" class="list-group">
|
||||||
|
<li class="list-group-item">
|
||||||
|
<table class="table table-bordered table-striped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<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('category')">Category</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'category'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<a href="" ng-click="order('room')">Room</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'room'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tr ng-repeat="veradevice in bridge.veradevices | unavailableVeraDeviceId | orderBy:predicate:reverse">
|
||||||
|
<td>{{veradevice.name}}</td>
|
||||||
|
<td>{{veradevice.id}}</td>
|
||||||
|
<td>{{veradevice.category}}</td>
|
||||||
|
<td>{{veradevice.room}}</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-danger" type="submit"
|
||||||
|
ng-click="deleteDeviceByMapId(veradevice.id, 'veraDevice')">Delete</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</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">
|
||||||
@@ -87,10 +127,6 @@
|
|||||||
<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>
|
||||||
<div class="clearfix visible-xs"></div>
|
|
||||||
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
|
|
||||||
ng-click="testUrl(device, 'on')">Test</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -101,10 +137,6 @@
|
|||||||
<textarea rows="3" class="form-control" id="device-off-url"
|
<textarea rows="3" class="form-control" id="device-off-url"
|
||||||
ng-model="device.offUrl" placeholder="URL to turn device off"></textarea>
|
ng-model="device.offUrl" placeholder="URL to turn device off"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="clearfix visible-xs"></div>
|
|
||||||
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
|
|
||||||
ng-click="testUrl(device, 'off')">Test</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tr ng-repeat="verascene in bridge.verascenes | orderBy:predicate:reverse">
|
<tr ng-repeat="verascene in bridge.verascenes | availableVeraSceneId | orderBy:predicate:reverse">
|
||||||
<td>{{verascene.name}}</td>
|
<td>{{verascene.name}}</td>
|
||||||
<td>{{verascene.id}}</td>
|
<td>{{verascene.id}}</td>
|
||||||
<td>{{verascene.room}}</td>
|
<td>{{verascene.room}}</td>
|
||||||
@@ -47,6 +47,41 @@
|
|||||||
</table>
|
</table>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h2 class="panel-title">Already Configured Vera Scenes <a ng-click="toggleScenes()"><span class={{imgScenesUrl}} aria-hidden="true"></a></h2>
|
||||||
|
</div>
|
||||||
|
<ul ng-if="scenesVisible" class="list-group">
|
||||||
|
<li class="list-group-item">
|
||||||
|
<table class="table table-bordered table-striped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<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('room')">Room</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'room'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tr ng-repeat="verascene in bridge.verascenes | unavailableVeraSceneId | orderBy:predicate:reverse">
|
||||||
|
<td>{{verascene.name}}</td>
|
||||||
|
<td>{{verascene.id}}</td>
|
||||||
|
<td>{{verascene.room}}</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-danger" type="submit"
|
||||||
|
ng-click="deleteDeviceByMapId(verascene.id, 'veraScene')">Delete</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</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">
|
||||||
@@ -75,10 +110,6 @@
|
|||||||
<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>
|
||||||
<div class="clearfix visible-xs"></div>
|
|
||||||
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
|
|
||||||
ng-click="testUrl(device, 'on')">Test</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -89,10 +120,6 @@
|
|||||||
<textarea rows="3" class="form-control" id="device-off-url"
|
<textarea rows="3" class="form-control" id="device-off-url"
|
||||||
ng-model="device.offUrl" placeholder="URL to turn device off"></textarea>
|
ng-model="device.offUrl" placeholder="URL to turn device off"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="clearfix visible-xs"></div>
|
|
||||||
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
|
|
||||||
ng-click="testUrl(device, 'off')">Test</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
Reference in New Issue
Block a user