mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-18 08:13:23 +00:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3f5946c9d | ||
|
|
12eab16f21 | ||
|
|
3df68047a9 | ||
|
|
0dd652f82a | ||
|
|
53af1a4dfd | ||
|
|
816a0025b1 | ||
|
|
405562809a | ||
|
|
4c87c6fce8 | ||
|
|
2fd0f7748b | ||
|
|
ed5f3b4b3c | ||
|
|
aad09b7527 | ||
|
|
0ae66da085 | ||
|
|
d344b764da | ||
|
|
c85b67fb9f | ||
|
|
a23d662444 | ||
|
|
4b98f799c2 | ||
|
|
acba2b5cae | ||
|
|
4dc818296a | ||
|
|
40123ed858 | ||
|
|
718ba5a5c2 | ||
|
|
2e6944d840 | ||
|
|
e29f12905d | ||
|
|
408b79d5d8 | ||
|
|
bf5ad2e23c | ||
|
|
59f1db285d | ||
|
|
203ed0b5d3 | ||
|
|
b443d16a11 | ||
|
|
295b1e1a30 | ||
|
|
c872f3543d | ||
|
|
23f2d2716d |
90
pom.xml
90
pom.xml
@@ -5,11 +5,11 @@
|
||||
|
||||
<groupId>com.bwssystems.HABridge</groupId>
|
||||
<artifactId>ha-bridge</artifactId>
|
||||
<version>0.4.9</version>
|
||||
<version>1.0.8</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HA Bridge</name>
|
||||
<description>Emulates a Philips Hue bridge to allow the Amazon Echo to hook up to other HA systems, i.e. Vera, using lightweight frameworks</description>
|
||||
<description>Emulates a Philips Hue bridge to allow the Amazon Echo to hook up to other HA systems, i.e. Vera or Harmony Hub, using lightweight frameworks</description>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
@@ -17,7 +17,19 @@
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.bwssytems</groupId>
|
||||
<artifactId>harmony-java-client</artifactId>
|
||||
<version>1.0.8</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sparkjava</groupId>
|
||||
<artifactId>spark-core</artifactId>
|
||||
@@ -58,9 +70,35 @@
|
||||
<artifactId>eval</artifactId>
|
||||
<version>0.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
<version>4.0-beta4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.igniterealtime.smack</groupId>
|
||||
<artifactId>smack-core</artifactId>
|
||||
<version>4.0.7</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<includes>
|
||||
<include>version.properties</include>
|
||||
</includes>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<excludes>
|
||||
<exclude>version.properties</exclude>
|
||||
</excludes>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
@@ -83,24 +121,42 @@
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
<exclude>META-INF/*.txt</exclude>
|
||||
<exclude>META-INF/maven/**</exclude>
|
||||
<exclude>META-INF/services/**</exclude>
|
||||
<exclude>META-INF/DEPENDENCIES</exclude>
|
||||
<exclude>about_files/**</exclude>
|
||||
<exclude>*.properties</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>org.slf4j:*</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>commons-logging:commons-logging</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>org.slf4j:*</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>commons-logging:commons-logging</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>xpp3:xpp3</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>org.igniterealtime.smack:*</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
<filter>
|
||||
<artifact>com.github.bwssytems:harmony-java-client</artifact>
|
||||
<includes>
|
||||
<include>**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
</filters>
|
||||
<transformers>
|
||||
<transformer
|
||||
|
||||
@@ -6,9 +6,12 @@ public class BridgeSettings {
|
||||
private String upnpresponseport;
|
||||
private String upnpdevicedb;
|
||||
private String veraaddress;
|
||||
private String harmonyaddress;
|
||||
private String harmonyuser;
|
||||
private String harmonypwd;
|
||||
private boolean upnpstrict;
|
||||
private boolean traceupnp;
|
||||
private boolean vtwocompatibility;
|
||||
private boolean devmode;
|
||||
|
||||
public String getUpnpConfigAddress() {
|
||||
return upnpconfigaddress;
|
||||
@@ -40,7 +43,24 @@ public class BridgeSettings {
|
||||
public void setVeraAddress(String veraAddress) {
|
||||
this.veraaddress = veraAddress;
|
||||
}
|
||||
|
||||
public String getHarmonyAddress() {
|
||||
return harmonyaddress;
|
||||
}
|
||||
public void setHarmonyAddress(String harmonyaddress) {
|
||||
this.harmonyaddress = harmonyaddress;
|
||||
}
|
||||
public String getHarmonyUser() {
|
||||
return harmonyuser;
|
||||
}
|
||||
public void setHarmonyUser(String harmonyuser) {
|
||||
this.harmonyuser = harmonyuser;
|
||||
}
|
||||
public String getHarmonyPwd() {
|
||||
return harmonypwd;
|
||||
}
|
||||
public void setHarmonyPwd(String harmonypwd) {
|
||||
this.harmonypwd = harmonypwd;
|
||||
}
|
||||
public boolean isUpnpStrict() {
|
||||
return upnpstrict;
|
||||
}
|
||||
@@ -53,17 +73,24 @@ public class BridgeSettings {
|
||||
public void setTraceupnp(boolean traceupnp) {
|
||||
this.traceupnp = traceupnp;
|
||||
}
|
||||
|
||||
public boolean isVtwocompatibility() {
|
||||
return vtwocompatibility;
|
||||
public boolean isDevMode() {
|
||||
return devmode;
|
||||
}
|
||||
public void setVtwocompatibility(boolean vtwocompatibility) {
|
||||
this.vtwocompatibility = vtwocompatibility;
|
||||
public void setDevMode(boolean devmode) {
|
||||
this.devmode = devmode;
|
||||
}
|
||||
|
||||
public Boolean isValidVera() {
|
||||
if(this.veraaddress.contains(Configuration.DEFAULT_VERA_ADDRESS))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
public Boolean isValidHarmony() {
|
||||
if(this.harmonyaddress.contains(Configuration.DEFAULT_HARMONY_ADDRESS))
|
||||
return false;
|
||||
if(this.harmonypwd == null || this.harmonypwd == "")
|
||||
return false;
|
||||
if(this.harmonyuser == null || this.harmonyuser == "")
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,5 +4,8 @@ public class Configuration {
|
||||
public final static String DEVICE_DB_DIRECTORY = "data/device.db";
|
||||
public final static String UPNP_RESPONSE_PORT = "50000";
|
||||
public final static String DEFAULT_VERA_ADDRESS = "1.1.1.1";
|
||||
public final static String DEFAULT_HARMONY_ADDRESS = "1.1.1.1";
|
||||
public final static String DEFAULT_HARMONY_USER = "";
|
||||
public final static String DEFAULT_HARMONY_PWD = "";
|
||||
public final static String DFAULT_WEB_PORT = "8080";
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.bwssystems.HABridge.devicemanagmeent.*;
|
||||
import com.bwssystems.HABridge.hue.HueMulator;
|
||||
import com.bwssystems.HABridge.upnp.UpnpListener;
|
||||
import com.bwssystems.HABridge.upnp.UpnpSettingsResource;
|
||||
import com.bwssystems.harmony.HarmonyServer;
|
||||
|
||||
public class HABridge {
|
||||
|
||||
@@ -33,13 +34,18 @@ public class HABridge {
|
||||
public static void main(String[] args) {
|
||||
Logger log = LoggerFactory.getLogger(HABridge.class);
|
||||
DeviceResource theResources;
|
||||
HarmonyServer myHarmonyServer;
|
||||
HueMulator theHueMulator;
|
||||
UpnpSettingsResource theSettingResponder;
|
||||
UpnpListener theUpnpListener;
|
||||
InetAddress address;
|
||||
String addressString;
|
||||
BridgeSettings bridgeSettings;
|
||||
Version theVersion;
|
||||
|
||||
theVersion = new Version();
|
||||
|
||||
log.info("HA Bridge (v" + theVersion.getVersion() + ") starting setup....");
|
||||
//get ip address for upnp requests
|
||||
try {
|
||||
address = InetAddress.getLocalHost();
|
||||
@@ -50,26 +56,35 @@ public class HABridge {
|
||||
}
|
||||
|
||||
bridgeSettings = new BridgeSettings();
|
||||
bridgeSettings.setServerPort(System.getProperty("server.port", Configuration.DFAULT_WEB_PORT));
|
||||
bridgeSettings.setUpnpConfigAddress(System.getProperty("upnp.config.address", addressString));
|
||||
bridgeSettings.setUpnpDeviceDb(System.getProperty("upnp.device.db", Configuration.DEVICE_DB_DIRECTORY));
|
||||
bridgeSettings.setUpnpResponsePort(System.getProperty("upnp.response.port", Configuration.UPNP_RESPONSE_PORT));
|
||||
bridgeSettings.setVeraAddress(System.getProperty("vera.address", Configuration.DEFAULT_VERA_ADDRESS));
|
||||
bridgeSettings.setHarmonyAddress(System.getProperty("harmony.address", Configuration.DEFAULT_HARMONY_ADDRESS));
|
||||
bridgeSettings.setHarmonyUser(System.getProperty("harmony.user", Configuration.DEFAULT_HARMONY_USER));
|
||||
bridgeSettings.setHarmonyPwd(System.getProperty("harmony.pwd", Configuration.DEFAULT_HARMONY_PWD));
|
||||
bridgeSettings.setUpnpStrict(Boolean.parseBoolean(System.getProperty("upnp.strict", "true")));
|
||||
bridgeSettings.setTraceupnp(Boolean.parseBoolean(System.getProperty("trace.upnp", "false")));
|
||||
bridgeSettings.setVtwocompatibility(Boolean.parseBoolean(System.getProperty("vtwo.compatibility", "false")));
|
||||
bridgeSettings.setDevMode(Boolean.parseBoolean(System.getProperty("dev.mode", "false")));
|
||||
|
||||
// sparkjava config directive to set ip address for the web server to listen on
|
||||
// ipAddress("0.0.0.0"); // not used
|
||||
// sparkjava config directive to set port for the web server to listen on
|
||||
bridgeSettings.setServerPort(System.getProperty("server.port", Configuration.DFAULT_WEB_PORT));
|
||||
port(Integer.valueOf(bridgeSettings.getServerPort()));
|
||||
// sparkjava config directive to set html static file location for Jetty
|
||||
staticFileLocation("/public");
|
||||
log.info("Starting setup....");
|
||||
//setup the harmony connection if available
|
||||
try {
|
||||
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
|
||||
theResources = new DeviceResource(bridgeSettings);
|
||||
theResources = new DeviceResource(bridgeSettings, theVersion, myHarmonyServer.getMyHarmony());
|
||||
// setup the class to handle the hue emulator rest api
|
||||
theHueMulator = new HueMulator(theResources.getDeviceRepository());
|
||||
theHueMulator = new HueMulator(theResources.getDeviceRepository(), myHarmonyServer.getMyHarmony());
|
||||
theHueMulator.setupServer();
|
||||
// setup the class to handle the upnp response rest api
|
||||
theSettingResponder = new UpnpSettingsResource(bridgeSettings);
|
||||
|
||||
50
src/main/java/com/bwssystems/HABridge/Version.java
Normal file
50
src/main/java/com/bwssystems/HABridge/Version.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package com.bwssystems.HABridge;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
public final class Version {
|
||||
|
||||
private String version;
|
||||
private String groupId;
|
||||
private String artifactId;
|
||||
private Properties prop;
|
||||
|
||||
public Version()
|
||||
{
|
||||
InputStream resourceAsStream =
|
||||
(InputStream) this.getClass().getResourceAsStream(
|
||||
"/version.properties"
|
||||
);
|
||||
this.prop = new Properties();
|
||||
|
||||
try
|
||||
{
|
||||
this.prop.load( resourceAsStream );
|
||||
this.version = this.prop.getProperty("version");
|
||||
this.groupId = this.prop.getProperty("groupId");
|
||||
this.artifactId = this.prop.getProperty("artifactId");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.version = "0.0.0";
|
||||
this.groupId = "no group";
|
||||
this.artifactId = "no artifact";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public String getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public String getArtifactId() {
|
||||
return artifactId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +1,5 @@
|
||||
package com.bwssystems.HABridge.api.hue;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by arm on 4/14/15.
|
||||
*/
|
||||
@@ -16,7 +11,6 @@ public class DeviceResponse {
|
||||
private String manufacturername;
|
||||
private String uniqueid;
|
||||
private String swversion;
|
||||
private Map<String, String> pointsymbol;
|
||||
|
||||
public DeviceState getState() {
|
||||
return state;
|
||||
@@ -74,27 +68,6 @@ public class DeviceResponse {
|
||||
this.swversion = swversion;
|
||||
}
|
||||
|
||||
public Map<String, String> getPointsymbol() {
|
||||
if(pointsymbol == null)
|
||||
{
|
||||
pointsymbol = new HashMap<>();
|
||||
pointsymbol.put("1", "none");
|
||||
pointsymbol.put("2", "none");
|
||||
pointsymbol.put("3", "none");
|
||||
pointsymbol.put("4", "none");
|
||||
pointsymbol.put("5", "none");
|
||||
pointsymbol.put("6", "none");
|
||||
pointsymbol.put("7", "none");
|
||||
pointsymbol.put("8", "none");
|
||||
}
|
||||
|
||||
return pointsymbol;
|
||||
}
|
||||
|
||||
public void setPointsymbol(Map<String, String> pointsymbol) {
|
||||
this.pointsymbol = pointsymbol;
|
||||
}
|
||||
|
||||
public static DeviceResponse createResponse(String name, String id){
|
||||
DeviceState deviceState = new DeviceState();
|
||||
DeviceResponse response = new DeviceResponse();
|
||||
@@ -104,21 +77,13 @@ public class DeviceResponse {
|
||||
deviceState.setEffect("none");
|
||||
deviceState.setAlert("none");
|
||||
deviceState.setBri(254);
|
||||
deviceState.setHue(15823);
|
||||
deviceState.setSat(88);
|
||||
deviceState.setCt(313);
|
||||
|
||||
List<Double> xv = new LinkedList<>();
|
||||
xv.add(Double.valueOf("0.4255"));
|
||||
xv.add(Double.valueOf("0.3998"));
|
||||
deviceState.setXy(xv);
|
||||
deviceState.setColormode("ct");
|
||||
response.setName(name);
|
||||
response.setUniqueid(id);
|
||||
response.setManufacturername("Philips");
|
||||
response.setType("Extended color light");
|
||||
response.setModelid("LCT001");
|
||||
response.setSwversion("65003148");
|
||||
response.setType("Dimmable light");
|
||||
response.setModelid("LWB004");
|
||||
response.setSwversion("66012040");
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.bwssystems.HABridge.api.hue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by arm on 4/14/15.
|
||||
@@ -8,14 +7,9 @@ import java.util.List;
|
||||
public class DeviceState {
|
||||
private boolean on;
|
||||
private int bri = 255;
|
||||
private int hue;
|
||||
private int sat;
|
||||
private String effect;
|
||||
private int ct;
|
||||
private String alert;
|
||||
private String colormode;
|
||||
private boolean reachable;
|
||||
private List<Double> xy;
|
||||
|
||||
public boolean isOn() {
|
||||
return on;
|
||||
@@ -33,22 +27,6 @@ public class DeviceState {
|
||||
this.bri = bri;
|
||||
}
|
||||
|
||||
public int getHue() {
|
||||
return hue;
|
||||
}
|
||||
|
||||
public void setHue(int hue) {
|
||||
this.hue = hue;
|
||||
}
|
||||
|
||||
public int getSat() {
|
||||
return sat;
|
||||
}
|
||||
|
||||
public void setSat(int sat) {
|
||||
this.sat = sat;
|
||||
}
|
||||
|
||||
public String getEffect() {
|
||||
return effect;
|
||||
}
|
||||
@@ -57,14 +35,6 @@ public class DeviceState {
|
||||
this.effect = effect;
|
||||
}
|
||||
|
||||
public int getCt() {
|
||||
return ct;
|
||||
}
|
||||
|
||||
public void setCt(int ct) {
|
||||
this.ct = ct;
|
||||
}
|
||||
|
||||
public String getAlert() {
|
||||
return alert;
|
||||
}
|
||||
@@ -73,14 +43,6 @@ public class DeviceState {
|
||||
this.alert = alert;
|
||||
}
|
||||
|
||||
public String getColormode() {
|
||||
return colormode;
|
||||
}
|
||||
|
||||
public void setColormode(String colormode) {
|
||||
this.colormode = colormode;
|
||||
}
|
||||
|
||||
public boolean isReachable() {
|
||||
return reachable;
|
||||
}
|
||||
@@ -89,14 +51,6 @@ public class DeviceState {
|
||||
this.reachable = reachable;
|
||||
}
|
||||
|
||||
public List<Double> getXy() {
|
||||
return xy;
|
||||
}
|
||||
|
||||
public void setXy(List<Double> xy) {
|
||||
this.xy = xy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeviceState{" +
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.bwssystems.HABridge.devicemanagmeent;
|
||||
|
||||
import static spark.Spark.get;
|
||||
import static spark.Spark.options;
|
||||
import static spark.Spark.post;
|
||||
import static spark.Spark.put;
|
||||
import static spark.Spark.delete;
|
||||
@@ -16,8 +17,10 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.BridgeSettings;
|
||||
import com.bwssystems.HABridge.JsonTransformer;
|
||||
import com.bwssystems.HABridge.Version;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.dao.DeviceRepository;
|
||||
import com.bwssystems.harmony.HarmonyHandler;
|
||||
import com.bwssystems.luupRequests.Sdata;
|
||||
import com.bwssystems.vera.VeraInfo;
|
||||
import com.google.gson.Gson;
|
||||
@@ -31,12 +34,16 @@ public class DeviceResource {
|
||||
|
||||
private DeviceRepository deviceRepository;
|
||||
private VeraInfo veraInfo;
|
||||
private Version version;
|
||||
private HarmonyHandler myHarmonyHandler;
|
||||
private static final Set<String> supportedVerbs = new HashSet<>(Arrays.asList("get", "put", "post"));
|
||||
|
||||
public DeviceResource(BridgeSettings theSettings) {
|
||||
public DeviceResource(BridgeSettings theSettings, Version theVersion, HarmonyHandler myHarmony) {
|
||||
super();
|
||||
deviceRepository = new DeviceRepository(theSettings.getUpnpDeviceDb());
|
||||
veraInfo = new VeraInfo(theSettings.getVeraAddress(), theSettings.isValidVera());
|
||||
this.deviceRepository = new DeviceRepository(theSettings.getUpnpDeviceDb());
|
||||
this.veraInfo = new VeraInfo(theSettings.getVeraAddress(), theSettings.isValidVera());
|
||||
this.myHarmonyHandler = myHarmony;
|
||||
this.version = theVersion;
|
||||
setupEndpoints();
|
||||
}
|
||||
|
||||
@@ -46,6 +53,15 @@ public class DeviceResource {
|
||||
|
||||
private void setupEndpoints() {
|
||||
log.info("HABridge device management service started.... ");
|
||||
// http://ip_address:port/api/devices CORS request
|
||||
options(API_CONTEXT, "application/json", (request, response) -> {
|
||||
response.status(HttpStatus.SC_OK);
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
|
||||
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
|
||||
response.header("Content-Type", "text/html; charset=utf-8");
|
||||
return "";
|
||||
});
|
||||
post(API_CONTEXT, "application/json", (request, response) -> {
|
||||
log.debug("Create a Device - request body: " + request.body());
|
||||
DeviceDescriptor device = new Gson().fromJson(request.body(), DeviceDescriptor.class);
|
||||
@@ -61,11 +77,21 @@ public class DeviceResource {
|
||||
deviceRepository.save(device);
|
||||
log.debug("Created a Device: " + request.body());
|
||||
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.status(HttpStatus.SC_CREATED);
|
||||
|
||||
return device;
|
||||
}, new JsonTransformer());
|
||||
|
||||
// http://ip_address:port/api/devices/:id CORS request
|
||||
options(API_CONTEXT + "/:id", "application/json", (request, response) -> {
|
||||
response.status(HttpStatus.SC_OK);
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
|
||||
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
|
||||
response.header("Content-Type", "text/html; charset=utf-8");
|
||||
return "";
|
||||
});
|
||||
put (API_CONTEXT + "/:id", "application/json", (request, response) -> {
|
||||
log.debug("Edit a Device - request body: " + request.body());
|
||||
DeviceDescriptor device = new Gson().fromJson(request.body(), DeviceDescriptor.class);
|
||||
@@ -127,6 +153,12 @@ public class DeviceResource {
|
||||
return null;
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/habridge/version", "application/json", (request, response) -> {
|
||||
log.debug("Get HA Bridge version: v" + version.getVersion());
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return "{\"version\":\"" + version.getVersion() + "\"}";
|
||||
});
|
||||
|
||||
get (API_CONTEXT + "/vera/devices", "application/json", (request, response) -> {
|
||||
log.debug("Get vera devices");
|
||||
Sdata sData = veraInfo.getSdata();
|
||||
@@ -150,5 +182,35 @@ public class DeviceResource {
|
||||
return sData.getScenes();
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/harmony/activities", "application/json", (request, response) -> {
|
||||
log.debug("Get harmony activities");
|
||||
if(myHarmonyHandler == null) {
|
||||
response.status(HttpStatus.SC_NOT_FOUND);
|
||||
return null;
|
||||
}
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return myHarmonyHandler.getActivities();
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/harmony/show", "application/json", (request, response) -> {
|
||||
log.debug("Get harmony current activity");
|
||||
if(myHarmonyHandler == null) {
|
||||
response.status(HttpStatus.SC_NOT_FOUND);
|
||||
return null;
|
||||
}
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return myHarmonyHandler.getCurrentActivity();
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/harmony/devices", "application/json", (request, response) -> {
|
||||
log.debug("Get harmony devices");
|
||||
if(myHarmonyHandler == null) {
|
||||
response.status(HttpStatus.SC_NOT_FOUND);
|
||||
return null;
|
||||
}
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return myHarmonyHandler.getDevices();
|
||||
}, new JsonTransformer());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,9 @@ import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
||||
import com.bwssystems.HABridge.api.hue.DeviceState;
|
||||
import com.bwssystems.HABridge.api.hue.HueApiResponse;
|
||||
import com.bwssystems.HABridge.dao.*;
|
||||
import com.bwssystems.harmony.ButtonPress;
|
||||
import com.bwssystems.harmony.HarmonyHandler;
|
||||
import com.bwssystems.harmony.RunActivity;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.gson.Gson;
|
||||
@@ -13,6 +16,7 @@ import com.google.gson.Gson;
|
||||
import net.java.dev.eval.Expression;
|
||||
|
||||
import static spark.Spark.get;
|
||||
import static spark.Spark.options;
|
||||
import static spark.Spark.post;
|
||||
import static spark.Spark.put;
|
||||
|
||||
@@ -51,21 +55,23 @@ public class HueMulator {
|
||||
private static final String HUE_CONTEXT = "/api";
|
||||
|
||||
private DeviceRepository repository;
|
||||
private HarmonyHandler myHarmony;
|
||||
private HttpClient httpClient;
|
||||
private ObjectMapper mapper;
|
||||
|
||||
|
||||
public HueMulator(DeviceRepository aDeviceRepository){
|
||||
public HueMulator(DeviceRepository aDeviceRepository, HarmonyHandler theHandler){
|
||||
httpClient = HttpClients.createDefault();
|
||||
mapper = new ObjectMapper(); //armzilla: work around Echo incorrect content type and breaking mapping. Map manually
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
repository = aDeviceRepository;
|
||||
myHarmony = theHandler;
|
||||
}
|
||||
|
||||
// This function sets up the sparkjava rest calls for the hue api
|
||||
public void setupServer() {
|
||||
log.info("Hue emulator service started....");
|
||||
// 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) -> {
|
||||
String userId = request.params(":userid");
|
||||
log.debug("hue lights list requested: " + userId + " from " + request.ip());
|
||||
@@ -80,7 +86,16 @@ public class HueMulator {
|
||||
return deviceResponseMap;
|
||||
} , new JsonTransformer());
|
||||
|
||||
// http://ip_address:port/api with body of user request returns json object for a success of user add
|
||||
// http://ip_address:port/api CORS request
|
||||
options(HUE_CONTEXT, "application/json", (request, response) -> {
|
||||
response.status(HttpStatus.SC_OK);
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.header("Access-Control-Allow-Methods", "GET, POST, PUT");
|
||||
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
|
||||
response.header("Content-Type", "text/html; charset=utf-8");
|
||||
return "";
|
||||
});
|
||||
// http://ip_address:port/api with body of user request returns json object for a success of user add
|
||||
post(HUE_CONTEXT, "application/json", (request, response) -> {
|
||||
UserCreateRequest aNewUser = null;
|
||||
String newUser = null;
|
||||
@@ -100,11 +115,21 @@ public class HueMulator {
|
||||
aDeviceType = "<not given>";
|
||||
log.debug("hue api user create requested for device type: " + aDeviceType + " and username: " + newUser);
|
||||
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.type("application/json; charset=utf-8");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return "[{\"success\":{\"username\":\"" + newUser + "\"}}]";
|
||||
} );
|
||||
|
||||
// http://ip_address:port/api/* CORS request
|
||||
options(HUE_CONTEXT + "/*", "application/json", (request, response) -> {
|
||||
response.status(HttpStatus.SC_OK);
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.header("Access-Control-Allow-Methods", "GET, POST, PUT");
|
||||
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
|
||||
response.header("Content-Type", "text/html; charset=utf-8");
|
||||
return "";
|
||||
});
|
||||
// http://ip_address:port/api/* with body of user request returns json object for a success of user add - This method is for Harmony Hub
|
||||
post(HUE_CONTEXT + "/*", "application/json", (request, response) -> {
|
||||
UserCreateRequest aNewUser = null;
|
||||
@@ -125,12 +150,13 @@ public class HueMulator {
|
||||
aDeviceType = "<not given>";
|
||||
log.debug("HH trace: hue api user create requested for device type: " + aDeviceType + " and username: " + newUser);
|
||||
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.type("application/json; charset=utf-8");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return "[{\"success\":{\"username\":\"" + newUser + "\"}}]";
|
||||
} );
|
||||
|
||||
// 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) -> {
|
||||
String userId = request.params(":userid");
|
||||
log.debug("hue api full state requested: " + userId + " from " + request.ip());
|
||||
@@ -154,7 +180,7 @@ public class HueMulator {
|
||||
return apiResponse;
|
||||
}, new JsonTransformer());
|
||||
|
||||
// http://ip_address:port/api/{userId}/lights/{lightId} returns json object for a given light
|
||||
// http://ip_address:port/api/{userId}/lights/{lightId} returns json object for a given light
|
||||
get(HUE_CONTEXT + "/:userid/lights/:id", "application/json", (request, response) -> {
|
||||
String userId = request.params(":userid");
|
||||
String lightId = request.params(":id");
|
||||
@@ -173,7 +199,16 @@ public class HueMulator {
|
||||
return lightResponse;
|
||||
}, new JsonTransformer());
|
||||
|
||||
// http://ip_address:port/api/{userId}/lights/{lightId}/state uses json object to set the lights state
|
||||
// http://ip_address:port/api/:userid/lights/:id/state CORS request
|
||||
options(HUE_CONTEXT + "/:userid/lights/:id/state", "application/json", (request, response) -> {
|
||||
response.status(HttpStatus.SC_OK);
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.header("Access-Control-Allow-Methods", "GET, POST, PUT");
|
||||
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
|
||||
response.header("Content-Type", "text/html; charset=utf-8");
|
||||
return "";
|
||||
});
|
||||
// http://ip_address:port/api/{userId}/lights/{lightId}/state uses json object to set the lights state
|
||||
put(HUE_CONTEXT + "/:userid/lights/:id/state", "application/json", (request, response) -> {
|
||||
/**
|
||||
* strangely enough the Echo sends a content type of application/x-www-form-urlencoded even though
|
||||
@@ -199,30 +234,63 @@ public class HueMulator {
|
||||
return null;
|
||||
}
|
||||
|
||||
String responseString;
|
||||
String url;
|
||||
String responseString =null;
|
||||
String url = null;
|
||||
if (state.isOn()) {
|
||||
responseString = "[{\"success\":{\"/lights/" + lightId + "/state/on\":true}}]";
|
||||
responseString = "[{\"success\":{\"/lights/" + lightId + "/state/on\":true}}";
|
||||
url = device.getOnUrl();
|
||||
} else {
|
||||
responseString = "[{\"success\":{\"/lights/" + lightId + "/state/on\":false}}]";
|
||||
} else if (request.body().contains("false")) {
|
||||
responseString = "[{\"success\":{\"/lights/" + lightId + "/state/on\":false}}";
|
||||
url = device.getOffUrl();
|
||||
}
|
||||
|
||||
//quick template
|
||||
String body;
|
||||
url = replaceIntensityValue(url, state.getBri());
|
||||
if (state.isOn())
|
||||
body = replaceIntensityValue(device.getContentBody(), state.getBri());
|
||||
|
||||
if(request.body().contains("bri"))
|
||||
{
|
||||
if(url == null)
|
||||
{
|
||||
url = device.getOnUrl();
|
||||
responseString = "[";
|
||||
}
|
||||
else
|
||||
responseString = responseString + ",";
|
||||
|
||||
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/bri\":" + state.getBri() + "}}]";
|
||||
}
|
||||
else
|
||||
body = replaceIntensityValue(device.getContentBodyOff(), state.getBri());
|
||||
//make call
|
||||
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);
|
||||
return null;
|
||||
responseString = responseString + "]";
|
||||
|
||||
|
||||
if(device.getDeviceType().toLowerCase().contains("activity"))
|
||||
{
|
||||
log.debug("executing activity to Harmony: " + url);
|
||||
RunActivity anActivity = new Gson().fromJson(url, RunActivity.class);
|
||||
myHarmony.startActivity(anActivity);
|
||||
}
|
||||
else if(device.getDeviceType().toLowerCase().contains("button"))
|
||||
{
|
||||
log.debug("executing button press to Harmony: " + url);
|
||||
ButtonPress aDeviceButton = new Gson().fromJson(url, ButtonPress.class);
|
||||
myHarmony.pressButton(aDeviceButton);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.debug("executing activity to Http " + (device.getHttpVerb() == null?"GET":device.getHttpVerb()) + ": " + url);
|
||||
// quick template
|
||||
String body;
|
||||
url = replaceIntensityValue(url, state.getBri());
|
||||
if (state.isOn())
|
||||
body = replaceIntensityValue(device.getContentBody(), state.getBri());
|
||||
else
|
||||
body = replaceIntensityValue(device.getContentBodyOff(), state.getBri());
|
||||
// make call
|
||||
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);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.type("application/json; charset=utf-8");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return responseString;
|
||||
@@ -288,7 +356,7 @@ public class HueMulator {
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(request);
|
||||
EntityUtils.consume(response.getEntity()); //close out inputstream ignore content
|
||||
log.debug("Execute on URL responded: " + response.getStatusLine().getStatusCode());
|
||||
log.debug((httpVerb == null?"GET":httpVerb) + " execute on URL responded: " + response.getStatusLine().getStatusCode());
|
||||
if(response.getStatusLine().getStatusCode() == 200){
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -27,8 +27,6 @@ public class UpnpListener {
|
||||
|
||||
private boolean traceupnp;
|
||||
|
||||
private boolean vTwoCompatibility;
|
||||
|
||||
public UpnpListener(BridgeSettings theSettings) {
|
||||
super();
|
||||
upnpResponsePort = Integer.valueOf(theSettings.getUpnpResponsePort());
|
||||
@@ -36,7 +34,6 @@ public class UpnpListener {
|
||||
responseAddress = theSettings.getUpnpConfigAddress();
|
||||
strict = theSettings.isUpnpStrict();
|
||||
traceupnp = theSettings.isTraceupnp();
|
||||
vTwoCompatibility = theSettings.isVtwocompatibility();
|
||||
}
|
||||
|
||||
public void startListening(){
|
||||
@@ -113,18 +110,18 @@ public class UpnpListener {
|
||||
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")))
|
||||
{
|
||||
if(traceupnp)
|
||||
log.info("Traceupnp: isSSDPDiscovery found message to be valid under strict rules - strict: " + strict + ", vTwo.Compatibility: " + vTwoCompatibility);
|
||||
log.info("Traceupnp: isSSDPDiscovery found message to be valid under strict rules - strict: " + strict);
|
||||
return true;
|
||||
}
|
||||
else if (!strict || vTwoCompatibility)
|
||||
else if (!strict)
|
||||
{
|
||||
if(traceupnp)
|
||||
log.info("Traceupnp: isSSDPDiscovery found message to be valid under loose rules - strict: " + strict + ", vTwo.Compatibility: " + vTwoCompatibility);
|
||||
log.info("Traceupnp: isSSDPDiscovery found message to be valid under loose rules - strict: " + strict);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(traceupnp)
|
||||
log.info("Traceupnp: isSSDPDiscovery found message to not be valid - strict: " + strict + ", vTwo.Compatibility: " + vTwoCompatibility);
|
||||
log.info("Traceupnp: isSSDPDiscovery found message to not be valid - strict: " + strict);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -135,20 +132,9 @@ public class UpnpListener {
|
||||
"SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/0.1\r\n" +
|
||||
"ST: urn:schemas-upnp-org:device:basic:1\r\n" +
|
||||
"USN: uuid:Socket-1_0-221438K0100073::urn:schemas-upnp-org:device:basic:1\r\n\r\n";
|
||||
String discoveryTemplateVTwo = "HTTP/1.1 200 OK\r\n" +
|
||||
"CACHE-CONTROL: max-age=86400\r\n" +
|
||||
"EXT:\r\n" +
|
||||
"LOCATION: http://%s:%s/description.xml\r\n" +
|
||||
"OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" +
|
||||
"01-NLS: %s\r\n" +
|
||||
"ST: urn:schemas-upnp-org:device:basic:1\r\n" +
|
||||
"USN: uuid:Socket-1_0-221438K0100073::urn:Belkin:device:**\r\n\r\n";
|
||||
protected void sendUpnpResponse(DatagramSocket socket, InetAddress requester, int sourcePort) throws IOException {
|
||||
String discoveryResponse = null;
|
||||
if(vTwoCompatibility)
|
||||
discoveryResponse = String.format(discoveryTemplateVTwo, responseAddress, httpServerPort, getRandomUUIDString());
|
||||
else
|
||||
discoveryResponse = String.format(discoveryTemplate, responseAddress, httpServerPort, getRandomUUIDString());
|
||||
discoveryResponse = String.format(discoveryTemplate, responseAddress, httpServerPort, getRandomUUIDString());
|
||||
if(traceupnp)
|
||||
log.info("Traceupnp: sendUpnpResponse: " + discoveryResponse);
|
||||
else
|
||||
|
||||
@@ -40,53 +40,6 @@ public class UpnpSettingsResource {
|
||||
+ "<depth>24</depth>\n" + "<url>hue_logo_3.png</url>\n" + "</icon>\n" + "</iconList>\n" + "</device>\n"
|
||||
+ "</root>\n";
|
||||
|
||||
private String hueTemplateVTwo = "<?xml version=\"1.0\"?>\n" +
|
||||
"<root xmlns=\"urn:schemas-upnp-org:device-1-0\">\n" +
|
||||
"<specVersion>\n" +
|
||||
"<major>1</major>\n" +
|
||||
"<minor>0</minor>\n" +
|
||||
"</specVersion>\n" +
|
||||
"<URLBase>http://%s:%s/</URLBase>\n" + //hostname string
|
||||
"<device>\n" +
|
||||
"<deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>\n" +
|
||||
"<friendlyName>Amazon-Echo-HA-Bridge (%s)</friendlyName>\n" +
|
||||
"<manufacturer>Royal Philips Electronics</manufacturer>\n" +
|
||||
"<manufacturerURL>http://www.bwssystems.com</manufacturerURL>\n" +
|
||||
"<modelDescription>Hue Emulator for Amazon Echo bridge</modelDescription>\n" +
|
||||
"<modelName>Philips hue bridge 2012</modelName>\n" +
|
||||
"<modelNumber>929000226503</modelNumber>\n" +
|
||||
"<modelURL>http://www.bwssystems.com/apps.html</modelURL>\n" +
|
||||
"<serialNumber>01189998819991197253</serialNumber>\n" +
|
||||
"<UDN>uuid:88f6698f-2c83-4393-bd03-cd54a9f8595</UDN>\n" +
|
||||
"<serviceList>\n" +
|
||||
"<service>\n" +
|
||||
"<serviceType>(null)</serviceType>\n" +
|
||||
"<serviceId>(null)</serviceId>\n" +
|
||||
"<controlURL>(null)</controlURL>\n" +
|
||||
"<eventSubURL>(null)</eventSubURL>\n" +
|
||||
"<SCPDURL>(null)</SCPDURL>\n" +
|
||||
"</service>\n" +
|
||||
"</serviceList>\n" +
|
||||
"<presentationURL>index.html</presentationURL>\n" +
|
||||
"<iconList>\n" +
|
||||
"<icon>\n" +
|
||||
"<mimetype>image/png</mimetype>\n" +
|
||||
"<height>48</height>\n" +
|
||||
"<width>48</width>\n" +
|
||||
"<depth>24</depth>\n" +
|
||||
"<url>hue_logo_0.png</url>\n" +
|
||||
"</icon>\n" +
|
||||
"<icon>\n" +
|
||||
"<mimetype>image/png</mimetype>\n" +
|
||||
"<height>120</height>\n" +
|
||||
"<width>120</width>\n" +
|
||||
"<depth>24</depth>\n" +
|
||||
"<url>hue_logo_3.png</url>\n" +
|
||||
"</icon>\n" +
|
||||
"</iconList>\n" +
|
||||
"</device>\n" +
|
||||
"</root>\n";
|
||||
|
||||
public UpnpSettingsResource(BridgeSettings theSettings) {
|
||||
super();
|
||||
this.theSettings = theSettings;
|
||||
@@ -102,10 +55,7 @@ public class UpnpSettingsResource {
|
||||
log.debug("upnp device settings requested: " + request.params(":id") + " from " + request.ip() + ":" + request.port());
|
||||
String portNumber = Integer.toString(request.port());
|
||||
String filledTemplate = null;
|
||||
if(theSettings.isVtwocompatibility())
|
||||
filledTemplate = String.format(hueTemplateVTwo, theSettings.getUpnpConfigAddress(), portNumber, theSettings.getUpnpConfigAddress());
|
||||
else
|
||||
filledTemplate = String.format(hueTemplate, theSettings.getUpnpConfigAddress(), portNumber, theSettings.getUpnpConfigAddress());
|
||||
filledTemplate = String.format(hueTemplate, theSettings.getUpnpConfigAddress(), portNumber, theSettings.getUpnpConfigAddress());
|
||||
if(theSettings.isTraceupnp())
|
||||
log.info("Traceupnp: upnp device settings response: " + filledTemplate);
|
||||
else
|
||||
|
||||
25
src/main/java/com/bwssystems/harmony/ButtonPress.java
Normal file
25
src/main/java/com/bwssystems/harmony/ButtonPress.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package com.bwssystems.harmony;
|
||||
|
||||
public class ButtonPress {
|
||||
private String device;
|
||||
private String button;
|
||||
public String getDevice() {
|
||||
return device;
|
||||
}
|
||||
public void setDevice(String device) {
|
||||
this.device = device;
|
||||
}
|
||||
public String getButton() {
|
||||
return button;
|
||||
}
|
||||
public void setButton(String button) {
|
||||
this.button = button;
|
||||
}
|
||||
public Boolean isValid() {
|
||||
if (device != null && !device.isEmpty()){
|
||||
if (button != null && !button.isEmpty())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
69
src/main/java/com/bwssystems/harmony/DevModeResponse.java
Normal file
69
src/main/java/com/bwssystems/harmony/DevModeResponse.java
Normal file
@@ -0,0 +1,69 @@
|
||||
package com.bwssystems.harmony;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.whistlingfish.harmony.config.Activity;
|
||||
import net.whistlingfish.harmony.config.Device;
|
||||
import net.whistlingfish.harmony.config.HarmonyConfig;
|
||||
|
||||
public class DevModeResponse {
|
||||
final Logger log = LoggerFactory.getLogger(DevModeResponse.class);
|
||||
|
||||
private final static String powerOff = "PowerOff";
|
||||
private HarmonyConfig harmonyConfig;
|
||||
private Activity currentActivity;
|
||||
|
||||
public DevModeResponse() {
|
||||
super();
|
||||
harmonyConfig = HarmonyConfig.parse(dataReader("/config.data"));
|
||||
this.currentActivity = harmonyConfig.getActivityByName(powerOff);
|
||||
}
|
||||
|
||||
public Activity getCurrentActivity() {
|
||||
return currentActivity;
|
||||
}
|
||||
|
||||
public void setCurrentActivity(Activity currentActivity) {
|
||||
this.currentActivity = currentActivity;
|
||||
}
|
||||
|
||||
public List<Activity> getActivities() {
|
||||
return harmonyConfig.getActivities();
|
||||
}
|
||||
|
||||
public List<Device> getDevices() {
|
||||
return harmonyConfig.getDevices();
|
||||
}
|
||||
|
||||
public HarmonyConfig getConfig() {
|
||||
return harmonyConfig;
|
||||
}
|
||||
|
||||
private String dataReader(String filePath) {
|
||||
|
||||
String content = null;
|
||||
try {
|
||||
InputStream input = getClass().getResourceAsStream(filePath);
|
||||
OutputStream out = new ByteArrayOutputStream();
|
||||
int read;
|
||||
byte[] bytes = new byte[1024];
|
||||
|
||||
while ((read = input.read(bytes)) != -1) {
|
||||
out.write(bytes, 0, read);
|
||||
}
|
||||
content = out.toString();
|
||||
} catch (IOException e) {
|
||||
log.error("Error reading the file: " + filePath + " message: " + e.getMessage(), e);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
}
|
||||
122
src/main/java/com/bwssystems/harmony/HarmonyHandler.java
Normal file
122
src/main/java/com/bwssystems/harmony/HarmonyHandler.java
Normal file
@@ -0,0 +1,122 @@
|
||||
package com.bwssystems.harmony;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.whistlingfish.harmony.HarmonyClient;
|
||||
import net.whistlingfish.harmony.config.Activity;
|
||||
import net.whistlingfish.harmony.config.Device;
|
||||
import net.whistlingfish.harmony.config.HarmonyConfig;
|
||||
|
||||
public class HarmonyHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger(HarmonyHandler.class);
|
||||
private HarmonyClient harmonyClient;
|
||||
private Boolean noopCalls;
|
||||
private Boolean devMode;
|
||||
private DevModeResponse devResponse;
|
||||
|
||||
public HarmonyHandler(HarmonyClient theClient, Boolean noopCallsSetting, DevModeResponse devResponseSetting) {
|
||||
super();
|
||||
noopCalls = noopCallsSetting;
|
||||
devMode = Boolean.TRUE;
|
||||
devResponse = null;
|
||||
if(devResponseSetting == null)
|
||||
devMode = Boolean.FALSE;
|
||||
else
|
||||
devResponse = devResponseSetting;
|
||||
harmonyClient = theClient;
|
||||
}
|
||||
|
||||
public List<Activity> getActivities() {
|
||||
log.debug("Harmony api activities list requested.");
|
||||
if(devMode)
|
||||
return devResponse.getActivities();
|
||||
|
||||
return harmonyClient.getConfig().getActivities();
|
||||
}
|
||||
|
||||
public List<Device> getDevices() {
|
||||
log.debug("Harmony api device list requested.");
|
||||
if(devMode)
|
||||
return devResponse.getDevices();
|
||||
|
||||
return harmonyClient.getConfig().getDevices();
|
||||
}
|
||||
|
||||
public HarmonyConfig getConfig() {
|
||||
log.debug("Harmony api config requested.");
|
||||
if(devMode)
|
||||
return devResponse.getConfig();
|
||||
|
||||
return harmonyClient.getConfig();
|
||||
}
|
||||
|
||||
public Activity getCurrentActivity() {
|
||||
log.debug("Harmony api current sctivity requested.");
|
||||
if(devMode)
|
||||
return devResponse.getCurrentActivity();
|
||||
|
||||
return harmonyClient.getCurrentActivity();
|
||||
}
|
||||
|
||||
public Boolean startActivity(RunActivity anActivity) {
|
||||
log.debug("Harmony api start activity requested for: " + anActivity.getName() + " noop mode: " + noopCalls);
|
||||
if (anActivity.isValid()) {
|
||||
try {
|
||||
if (noopCalls || devMode) {
|
||||
if(devMode)
|
||||
{
|
||||
if(anActivity != null)
|
||||
devResponse.setCurrentActivity(devResponse.getConfig().getActivityByName(anActivity.getName()));
|
||||
}
|
||||
|
||||
log.info("noop mode: Harmony api start activity requested for: " + anActivity.getName());
|
||||
}
|
||||
else
|
||||
harmonyClient.startActivity(Integer.parseInt(anActivity.getName()));
|
||||
} catch (IllegalArgumentException e) {
|
||||
try {
|
||||
if (!noopCalls)
|
||||
harmonyClient.startActivityByName(anActivity.getName());
|
||||
} catch (IllegalArgumentException ei) {
|
||||
log.error("Error in finding activity: " + anActivity.getName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.error("Error in finding activity: " + anActivity.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Boolean pressButton(ButtonPress aDeviceButton) {
|
||||
log.debug("Harmony api press a button requested for device: " + aDeviceButton.getDevice() + " and a for button: " + aDeviceButton.getButton() + " noop mode: " + noopCalls);
|
||||
if (aDeviceButton.isValid()) {
|
||||
try {
|
||||
if (noopCalls || devMode) {
|
||||
log.info("noop mode: Harmony api press a button requested for device: " + aDeviceButton.getDevice() + " and a for button: " + aDeviceButton.getButton());
|
||||
}
|
||||
else
|
||||
harmonyClient.pressButton(Integer.parseInt(aDeviceButton.getDevice()), aDeviceButton.getButton());
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
try {
|
||||
if (!noopCalls)
|
||||
harmonyClient.pressButton(aDeviceButton.getDevice(), aDeviceButton.getButton());
|
||||
} catch (IllegalArgumentException ei) {
|
||||
log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
81
src/main/java/com/bwssystems/harmony/HarmonyServer.java
Normal file
81
src/main/java/com/bwssystems/harmony/HarmonyServer.java
Normal file
@@ -0,0 +1,81 @@
|
||||
package com.bwssystems.harmony;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.BridgeSettings;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
import net.whistlingfish.harmony.ActivityChangeListener;
|
||||
import net.whistlingfish.harmony.HarmonyClient;
|
||||
import net.whistlingfish.harmony.HarmonyClientModule;
|
||||
import net.whistlingfish.harmony.config.Activity;
|
||||
import net.whistlingfish.harmony.protocol.OAReplyProvider;
|
||||
|
||||
public class HarmonyServer {
|
||||
@Inject
|
||||
private HarmonyClient harmonyClient;
|
||||
|
||||
private HarmonyHandler myHarmony;
|
||||
private DevModeResponse devResponse;
|
||||
private OAReplyProvider dummyProvider;
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(HarmonyServer.class);
|
||||
|
||||
public HarmonyServer() {
|
||||
super();
|
||||
myHarmony = null;
|
||||
dummyProvider = null;
|
||||
}
|
||||
|
||||
public static HarmonyServer setup(BridgeSettings bridgeSettings) throws Exception {
|
||||
if(!bridgeSettings.isValidHarmony()) {
|
||||
return new HarmonyServer();
|
||||
}
|
||||
Injector injector = null;
|
||||
if(!bridgeSettings.isDevMode())
|
||||
injector = Guice.createInjector(new HarmonyClientModule());
|
||||
HarmonyServer mainObject = new HarmonyServer();
|
||||
if(!bridgeSettings.isDevMode())
|
||||
injector.injectMembers(mainObject);
|
||||
mainObject.execute(bridgeSettings);
|
||||
return mainObject;
|
||||
}
|
||||
|
||||
private void execute(BridgeSettings mySettings) throws Exception {
|
||||
Boolean noopCalls = Boolean.parseBoolean(System.getProperty("noop.calls", "false"));
|
||||
String modeString = "";
|
||||
if(dummyProvider != null)
|
||||
log.debug("something is very wrong as dummyProvider is not null...");
|
||||
if(mySettings.isDevMode())
|
||||
modeString = " (development mode)";
|
||||
if(noopCalls)
|
||||
modeString = " (no op calls to harmony)";
|
||||
log.info("setup initiated " + modeString + "....");
|
||||
if(mySettings.isDevMode())
|
||||
{
|
||||
harmonyClient = null;
|
||||
devResponse = new DevModeResponse();
|
||||
}
|
||||
else {
|
||||
devResponse = null;
|
||||
harmonyClient.addListener(new ActivityChangeListener() {
|
||||
@Override
|
||||
public void activityStarted(Activity activity) {
|
||||
log.info(format("activity changed: [%d] %s", activity.getId(), activity.getLabel()));
|
||||
}
|
||||
});
|
||||
harmonyClient.connect(mySettings.getHarmonyAddress(), mySettings.getHarmonyUser(), mySettings.getHarmonyPwd());
|
||||
}
|
||||
myHarmony = new HarmonyHandler(harmonyClient, noopCalls, devResponse);
|
||||
}
|
||||
|
||||
public HarmonyHandler getMyHarmony() {
|
||||
return myHarmony;
|
||||
}
|
||||
}
|
||||
18
src/main/java/com/bwssystems/harmony/RunActivity.java
Normal file
18
src/main/java/com/bwssystems/harmony/RunActivity.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package com.bwssystems.harmony;
|
||||
|
||||
public class RunActivity {
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public Boolean isValid() {
|
||||
if (name != null && !name.isEmpty())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
1
src/main/resources/config.data
Normal file
1
src/main/resources/config.data
Normal file
File diff suppressed because one or more lines are too long
@@ -16,7 +16,7 @@
|
||||
<body>
|
||||
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container">
|
||||
<div class="container" ng-controller="VersionController">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
@@ -36,7 +36,7 @@
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
<li><a href="http://www.bwssystems.com" target="_blank">Developed by BWS Systems</a></li>
|
||||
<li><a href="http://www.amazon.com/echo" target="_blank">Amazon Echo</a></li>
|
||||
<li><a href="">HA Bridge Version 0.4.9</a></li>
|
||||
<li><a href="">HA Bridge Version {{bridge.habridgeversion}}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -4,8 +4,11 @@ var app = angular.module('habridge', [
|
||||
|
||||
app.config(function ($routeProvider) {
|
||||
$routeProvider.when('/#', {
|
||||
templateUrl: 'views/configuration.html',
|
||||
templateUrl: 'views/nonconfiguration.html',
|
||||
controller: 'ViewingController'
|
||||
}).when('/show', {
|
||||
templateUrl: 'views/configuration.html',
|
||||
controller: 'ViewingController'
|
||||
}).when('/editor', {
|
||||
templateUrl: 'views/editor.html',
|
||||
controller: 'AddingController'
|
||||
@@ -18,8 +21,14 @@ app.config(function ($routeProvider) {
|
||||
}).when('/verascenes', {
|
||||
templateUrl: 'views/verascene.html',
|
||||
controller: 'AddingController'
|
||||
}).when('/harmonydevices', {
|
||||
templateUrl: 'views/harmonydevice.html',
|
||||
controller: 'AddingController'
|
||||
}).when('/harmonyactivities', {
|
||||
templateUrl: 'views/harmonyactivity.html',
|
||||
controller: 'AddingController'
|
||||
}).otherwise({
|
||||
templateUrl: 'views/configuration.html',
|
||||
templateUrl: 'views/nonconfiguration.html',
|
||||
controller: 'ViewingController'
|
||||
})
|
||||
});
|
||||
@@ -27,6 +36,8 @@ app.config(function ($routeProvider) {
|
||||
app.run( function (bridgeService) {
|
||||
bridgeService.loadBridgeSettings();
|
||||
bridgeService.updateShowVera();
|
||||
bridgeService.updateShowHarmony();
|
||||
bridgeService.getHABridgeVersion();
|
||||
});
|
||||
|
||||
app.factory('BridgeSettings', function() {
|
||||
@@ -37,9 +48,10 @@ app.factory('BridgeSettings', function() {
|
||||
BridgeSettings.upnpdevicedb = "";
|
||||
BridgeSettings.upnpresponseport = "";
|
||||
BridgeSettings.veraaddress = "";
|
||||
BridgeSettings.harmonyaddress = "";
|
||||
BridgeSettings.upnpstrict = "";
|
||||
BridgeSettings.traceupnp = "";
|
||||
BridgeSettings.vtwocompatibility = "";
|
||||
BridgeSettings.devmode = "";
|
||||
|
||||
BridgeSettings.setupnpconfigaddress = function(aconfigaddress){
|
||||
BridgeSettings.upnpconfigaddress = aconfigaddress;
|
||||
@@ -60,14 +72,17 @@ app.factory('BridgeSettings', function() {
|
||||
BridgeSettings.setveraaddress = function(averaaddress){
|
||||
BridgeSettings.veraaddress = averaaddress;
|
||||
};
|
||||
BridgeSettings.setharmonyaddress = function(aharmonyaddress){
|
||||
BridgeSettings.harmonyaddress = aharmonyaddress;
|
||||
};
|
||||
BridgeSettings.setupnpstrict = function(aupnpstrict){
|
||||
BridgeSettings.upnpstrict = aupnpstrict;
|
||||
};
|
||||
BridgeSettings.settraceupnp = function(atraceupnp){
|
||||
BridgeSettings.traceupnp = atraceupnp;
|
||||
};
|
||||
BridgeSettings.setvtwocompatibility = function(avtwocompatibility){
|
||||
BridgeSettings.vtwocompatibility = avtwocompatibility;
|
||||
BridgeSettings.setdevmode = function(adevmode){
|
||||
BridgeSettings.devmode = adevmode;
|
||||
};
|
||||
|
||||
return BridgeSettings;
|
||||
@@ -76,7 +91,7 @@ app.factory('BridgeSettings', function() {
|
||||
app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
var self = this;
|
||||
self.BridgeSettings = BridgeSettings;
|
||||
this.state = {base: window.location.origin + "/api/devices", upnpbase: window.location.origin + "/upnp/settings", devices: [], device: [], error: "", showVera: false};
|
||||
this.state = {base: window.location.origin + "/api/devices", upnpbase: window.location.origin + "/upnp/settings", huebase: window.location.origin + "/api", devices: [], device: [], error: "", showVera: false, showHarmony: false, habridgeversion: ""};
|
||||
|
||||
this.viewDevices = function () {
|
||||
this.state.error = "";
|
||||
@@ -88,8 +103,24 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
if (error.data) {
|
||||
self.state.error = error.data.message;
|
||||
} else {
|
||||
self.state.error = "If you're not seeing any devices, you may be running into problems with CORS. " +
|
||||
"You can work around this by running a fresh launch of Chrome with the --disable-web-security flag.";
|
||||
self.state.error = "Some error occurred.";
|
||||
}
|
||||
console.log(error);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
this.getHABridgeVersion = function () {
|
||||
this.state.error = "";
|
||||
return $http.get(this.state.base + "/habridge/version").then(
|
||||
function (response) {
|
||||
self.state.habridgeversion = response.data.version;
|
||||
},
|
||||
function (error) {
|
||||
if (error.data) {
|
||||
self.state.error = error.data.message;
|
||||
} else {
|
||||
self.state.error = "cannot get version";
|
||||
}
|
||||
console.log(error);
|
||||
}
|
||||
@@ -105,13 +136,18 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
self.BridgeSettings.setupnpdevicedb(response.data.upnpdevicedb);
|
||||
self.BridgeSettings.setupnpresponseport(response.data.upnpresponseport);
|
||||
self.BridgeSettings.setveraaddress(response.data.veraaddress);
|
||||
self.BridgeSettings.setharmonyaddress(response.data.harmonyaddress);
|
||||
self.BridgeSettings.settraceupnp(response.data.traceupnp);
|
||||
self.BridgeSettings.setupnpstrict(response.data.upnpstrict);
|
||||
self.BridgeSettings.setvtwocompatibility(response.data.vtwocompatibility);
|
||||
self.BridgeSettings.setdevmode(response.data.devmode);
|
||||
if(self.BridgeSettings.veraaddress == "1.1.1.1" || self.BridgeSettings.veraaddress == "")
|
||||
self.state.showVera = false;
|
||||
else
|
||||
self.state.showVera = true;
|
||||
if(self.BridgeSettings.harmonyaddress == "1.1.1.1" || self.BridgeSettings.harmonyaddress == "")
|
||||
self.state.showHarmony = false;
|
||||
else
|
||||
self.state.showHarmony = true;
|
||||
},
|
||||
function (error) {
|
||||
if (error.data) {
|
||||
@@ -132,9 +168,17 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateShowHarmony = function () {
|
||||
if(self.BridgeSettings.harmonyaddress == "1.1.1.1" || self.BridgeSettings.harmonyaddress == "")
|
||||
this.state.showHarmony = false;
|
||||
else
|
||||
this.state.showHarmony = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.viewVeraDevices = function () {
|
||||
this.state.error = "";
|
||||
if(BridgeSettings.veraaddress == "1.1.1.1" || BridgeSettings.veraaddress == "")
|
||||
if(!this.state.showVera)
|
||||
return;
|
||||
this.state.error = "";
|
||||
return $http.get(this.state.base + "/vera/devices").then(
|
||||
@@ -153,7 +197,7 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
|
||||
this.viewVeraScenes = function () {
|
||||
this.state.error = "";
|
||||
if(BridgeSettings.veraaddress == "1.1.1.1" || BridgeSettings.veraaddress == "")
|
||||
if(!this.state.showVera)
|
||||
return;
|
||||
return $http.get(this.state.base + "/vera/scenes").then(
|
||||
function (response) {
|
||||
@@ -169,8 +213,46 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
);
|
||||
};
|
||||
|
||||
this.viewHarmonyActivities = function () {
|
||||
this.state.error = "";
|
||||
if(!this.state.showHarmony)
|
||||
return;
|
||||
return $http.get(this.state.base + "/harmony/activities").then(
|
||||
function (response) {
|
||||
self.state.harmonyactivities = response.data;
|
||||
},
|
||||
function (error) {
|
||||
if (error.data) {
|
||||
$window.alert("Get Harmony Activities Error: " + error.data.message);
|
||||
} else {
|
||||
$window.alert("Get Harmony Activities Error: unknown");
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
this.viewHarmonyDevices = function () {
|
||||
this.state.error = "";
|
||||
if(!this.state.showHarmony)
|
||||
return;
|
||||
return $http.get(this.state.base + "/harmony/devices").then(
|
||||
function (response) {
|
||||
self.state.harmonydevices = response.data;
|
||||
},
|
||||
function (error) {
|
||||
if (error.data) {
|
||||
$window.alert("Get Harmony Devices Error: " + error.data.message);
|
||||
} else {
|
||||
$window.alert("Get Harmony Devices Error: unknown");
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
this.addDevice = function (id, name, type, onUrl, offUrl, httpVerb, contentType, contentBody, contentBodyOff) {
|
||||
this.state.error = "";
|
||||
if(httpVerb != null && httpVerb != "")
|
||||
type = "custom";
|
||||
if (id) {
|
||||
var putUrl = this.state.base + "/" + id;
|
||||
return $http.put(putUrl, {
|
||||
@@ -197,6 +279,8 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
} else {
|
||||
if(type == null || type == "")
|
||||
type = "switch";
|
||||
if(httpVerb != null && httpVerb != "")
|
||||
type = "custom";
|
||||
return $http.post(this.state.base, {
|
||||
name: name,
|
||||
deviceType: type,
|
||||
@@ -246,6 +330,7 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
|
||||
bridgeService.viewDevices();
|
||||
$scope.bridge = bridgeService.state;
|
||||
bridgeService.updateShowVera();
|
||||
bridgeService.updateShowHarmony();
|
||||
$scope.predicate = '';
|
||||
$scope.reverse = true;
|
||||
$scope.order = function(predicate) {
|
||||
@@ -257,6 +342,18 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
|
||||
};
|
||||
$scope.testUrl = function (device, type) {
|
||||
if(type == "on") {
|
||||
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) {
|
||||
@@ -279,6 +376,18 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
|
||||
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) {
|
||||
@@ -319,8 +428,11 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
|
||||
bridgeService.device = $scope.device;
|
||||
bridgeService.viewVeraDevices();
|
||||
bridgeService.viewVeraScenes();
|
||||
bridgeService.viewHarmonyActivities();
|
||||
bridgeService.viewHarmonyDevices();
|
||||
$scope.bridge = bridgeService.state;
|
||||
bridgeService.updateShowVera();
|
||||
bridgeService.updateShowHarmony();
|
||||
$scope.device = bridgeService.state.device;
|
||||
$scope.predicate = '';
|
||||
$scope.reverse = true;
|
||||
@@ -397,8 +509,34 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
|
||||
+ verascene.id;
|
||||
};
|
||||
|
||||
$scope.testUrl = function (url) {
|
||||
$scope.buildActivityUrls = function (harmonyactivity) {
|
||||
$scope.device.deviceType = "activity";
|
||||
$scope.device.name = harmonyactivity.label;
|
||||
$scope.device.onUrl = "{\"name\":\"" + harmonyactivity.id + "\"}";
|
||||
$scope.device.offUrl = "{\"name\":\"-1\"}";
|
||||
};
|
||||
|
||||
$scope.buildButtonUrls = function (harmonydevice, onbutton, offbutton) {
|
||||
$scope.device.deviceType = "button";
|
||||
$scope.device.name = harmonydevice.label;
|
||||
$scope.device.onUrl = "{\"device\":\"" + harmonydevice.id + "\",\"button\":\"" + onbutton + "\"}";
|
||||
$scope.device.offUrl = "{\"device\":\"" + harmonydevice.id + "\",\"button\":\"" + offbutton + "\"}";
|
||||
};
|
||||
|
||||
$scope.testUrl = function (device, type) {
|
||||
if(type == "on") {
|
||||
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) {
|
||||
@@ -421,6 +559,18 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
|
||||
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) {
|
||||
@@ -467,4 +617,8 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
|
||||
|
||||
app.controller('ErrorsController', function ($scope, bridgeService) {
|
||||
$scope.bridge = bridgeService.state;
|
||||
});
|
||||
});
|
||||
|
||||
app.controller('VersionController', function ($scope, bridgeService) {
|
||||
$scope.bridge = bridgeService.state;
|
||||
});
|
||||
@@ -2,72 +2,11 @@
|
||||
<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 class="panel panel-default bridgeServer">
|
||||
<div class="panel-heading">
|
||||
<h1 class="panel-title">Bridge settings</h1>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-xs-12 col-sm-3 control-label" for="bridge-base">Bridge
|
||||
server</label>
|
||||
|
||||
<div class="col-xs-8 col-sm-7">
|
||||
<input id="bridge-base" class="form-control" type="text"
|
||||
ng-model="bridge.base" placeholder="URL to bridge">
|
||||
</div>
|
||||
<button type="submit" class="col-xs-2 col-sm-1 btn btn-primary"
|
||||
ng-click="setBridgeUrl(bridge.base)">Load</button>
|
||||
<button type="submit" class="col-xs-2 col-sm-1 btn btn-primary"
|
||||
ng-click="testUrl(bridge.base)">Go</button>
|
||||
</div>
|
||||
</form>
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Setting</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>upnp.config.address</td>
|
||||
<td>{{BridgeSettings.upnpconfigaddress}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>server.port</td>
|
||||
<td>{{BridgeSettings.serverport}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>upnp.devices.db</td>
|
||||
<td>{{BridgeSettings.upnpdevicedb}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>upnp.response.port</td>
|
||||
<td>{{BridgeSettings.upnpresponseport}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>vera.address</td>
|
||||
<td>{{BridgeSettings.veraaddress}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>upnp.strict</td>
|
||||
<td>{{BridgeSettings.upnpstrict}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>trace.upnp</td>
|
||||
<td>{{BridgeSettings.traceupnp}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>vtwo.compatibility</td>
|
||||
<td>{{BridgeSettings.vtwocompatibility}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-controller="ErrorsController">
|
||||
<div ng-if="bridge.error"
|
||||
@@ -117,4 +56,73 @@
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default bridgeServer">
|
||||
<div class="panel-heading">
|
||||
<a href="#/"><span class="glyphicon glyphicon-minus" aria-hidden="true"></span></a>
|
||||
<h1 class="panel-title">Bridge settings</h1>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-xs-12 col-sm-3 control-label" for="bridge-base">Bridge
|
||||
server</label>
|
||||
|
||||
<div class="col-xs-8 col-sm-7">
|
||||
<input id="bridge-base" class="form-control" type="text"
|
||||
ng-model="bridge.base" placeholder="URL to bridge">
|
||||
</div>
|
||||
<button type="submit" class="col-xs-2 col-sm-1 btn btn-primary"
|
||||
ng-click="setBridgeUrl(bridge.base)">Load</button>
|
||||
<button type="submit" class="col-xs-2 col-sm-1 btn btn-primary"
|
||||
ng-click="testUrl(bridge.base)">Go</button>
|
||||
</div>
|
||||
</form>
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Setting</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>upnp.config.address</td>
|
||||
<td>{{BridgeSettings.upnpconfigaddress}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>server.port</td>
|
||||
<td>{{BridgeSettings.serverport}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>upnp.devices.db</td>
|
||||
<td>{{BridgeSettings.upnpdevicedb}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>upnp.response.port</td>
|
||||
<td>{{BridgeSettings.upnpresponseport}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>vera.address</td>
|
||||
<td>{{BridgeSettings.veraaddress}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>harmony.address</td>
|
||||
<td>{{BridgeSettings.harmonyaddress}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>upnp.strict</td>
|
||||
<td>{{BridgeSettings.upnpstrict}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>trace.upnp</td>
|
||||
<td>{{BridgeSettings.traceupnp}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dev.mode</td>
|
||||
<td>{{BridgeSettings.devmode}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
<li role="presentation"><a href="#">Configuration</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
||||
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
||||
<li role="presentation" class="active"><a href="#/editdevice">Edit Device</a></li>
|
||||
</ul>
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
<li role="presentation"><a href="#">Configuration</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
||||
<li role="presentation" class="active"><a href="#/editor">Manual Add</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
||||
<div class="panel panel-default bridgeServer" ng-if="bridge.showVera">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">Generate a new device/scene/control point</h2>
|
||||
</div>
|
||||
|
||||
89
src/main/resources/public/views/harmonyactivity.html
Normal file
89
src/main/resources/public/views/harmonyactivity.html
Normal file
@@ -0,0 +1,89 @@
|
||||
<ul class="nav nav-pills" role="tablist">
|
||||
<li role="presentation"><a href="#">Configuration</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
||||
<li role="presentation" class="active"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
||||
<li role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
||||
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">Harmony Activity List</h2>
|
||||
</div>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<p class="text-muted">You can select a Harmony Activity and generate
|
||||
the add activity box selections automatically.</p>
|
||||
|
||||
<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>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="harmonyactivity in bridge.harmonyactivities | orderBy:predicate:reverse">
|
||||
<td>{{harmonyactivity.label}}</td>
|
||||
<td>{{harmonyactivity.id}}</td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildActivityUrls(harmonyactivity)">Generate
|
||||
Activity URLs</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">Add a Harmony Activity</h2>
|
||||
</div>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<form class="form-horizontal" ng-submit="addDevice()">
|
||||
<div class="form-group">
|
||||
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
|
||||
</label>
|
||||
|
||||
<div class="col-xs-8 col-sm-7">
|
||||
<input type="text" class="form-control" id="device-name"
|
||||
ng-model="device.name" placeholder="Device Name">
|
||||
</div>
|
||||
<button type="submit" class="col-xs-4 col-sm-2 btn btn-primary">
|
||||
Add Activity</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<label class="col-xs-12 col-sm-2 control-label" for="device-on-url">On
|
||||
URL </label>
|
||||
|
||||
<div class="col-xs-8 col-sm-7">
|
||||
<textarea rows="3" class="form-control" id="device-on-url"
|
||||
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<label class="col-xs-12 col-sm-2 control-label"
|
||||
for="device-off-url">Off URL </label>
|
||||
|
||||
<div class="col-xs-8 col-sm-7">
|
||||
<textarea rows="3" class="form-control" id="device-off-url"
|
||||
ng-model="device.offUrl" placeholder="URL to turn device off"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
105
src/main/resources/public/views/harmonydevice.html
Normal file
105
src/main/resources/public/views/harmonydevice.html
Normal file
@@ -0,0 +1,105 @@
|
||||
<ul class="nav nav-pills" role="tablist">
|
||||
<li role="presentation"><a href="#">Configuration</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
||||
<li role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
||||
<li role="presentation" class="active"><a href="#/harmonydevices">Harmony Devices</a></li>
|
||||
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">Harmony Device List</h2>
|
||||
</div>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<p class="text-muted">You can select a Harmony Device and Button and generate
|
||||
the add button box selections automatically.</p>
|
||||
|
||||
<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>On Button</th>
|
||||
<th>Off Button</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="harmonydevice in bridge.harmonydevices | orderBy:predicate:reverse">
|
||||
<td>{{harmonydevice.label}}</td>
|
||||
<td>{{harmonydevice.id}}</td>
|
||||
<td>
|
||||
<select name="device-ctrlon" id="device-ctrlon" ng-model="devicectrlon">
|
||||
<optgroup ng-repeat="ctrlon in harmonydevice.controlGroup" label="{{ctrlon.name}}">
|
||||
<option ng-repeat="funcon in ctrlon.function">{{funcon.name}}</option>
|
||||
</optgroup >
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<select name="device-ctrloff" id="device-ctrloff" ng-model="devicectrloff">
|
||||
<optgroup ng-repeat="ctrloff in harmonydevice.controlGroup" label="{{ctrloff.name}}">
|
||||
<option ng-repeat="funcoff in ctrloff.function">{{funcoff.name}}</option>
|
||||
</optgroup >
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildButtonUrls(harmonydevice, devicectrlon, devicectrloff)">Generate
|
||||
Button URLs</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">Add a Harmony Button</h2>
|
||||
</div>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<form class="form-horizontal" ng-submit="addDevice()">
|
||||
<div class="form-group">
|
||||
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
|
||||
</label>
|
||||
|
||||
<div class="col-xs-8 col-sm-7">
|
||||
<input type="text" class="form-control" id="device-name"
|
||||
ng-model="device.name" placeholder="Device Name">
|
||||
</div>
|
||||
<button type="submit" class="col-xs-4 col-sm-2 btn btn-primary">
|
||||
Add Button</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<label class="col-xs-12 col-sm-2 control-label" for="device-on-url">On
|
||||
URL </label>
|
||||
|
||||
<div class="col-xs-8 col-sm-7">
|
||||
<textarea rows="3" class="form-control" id="device-on-url"
|
||||
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<label class="col-xs-12 col-sm-2 control-label"
|
||||
for="device-off-url">Off URL </label>
|
||||
|
||||
<div class="col-xs-8 col-sm-7">
|
||||
<textarea rows="3" class="form-control" id="device-off-url"
|
||||
ng-model="device.offUrl" placeholder="URL to turn device off"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
64
src/main/resources/public/views/nonconfiguration.html
Normal file
64
src/main/resources/public/views/nonconfiguration.html
Normal file
@@ -0,0 +1,64 @@
|
||||
<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>
|
||||
@@ -2,6 +2,8 @@
|
||||
<li role="presentation"><a href="#">Configuration</a></li>
|
||||
<li role="presentation" class="active"><a href="#/veradevices">Vera Devices</a></li>
|
||||
<li role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
||||
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
<li role="presentation"><a href="#">Configuration</a></li>
|
||||
<li role="presentation"><a href="#/veradevices">Vera Devices</a></li>
|
||||
<li role="presentation" class="active"><a href="#/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
||||
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
||||
</ul>
|
||||
|
||||
@@ -12,7 +14,7 @@
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<p class="text-muted">You can select a Vera scene and generate
|
||||
the add device box selections automatically.</p>
|
||||
the add scene box selections automatically.</p>
|
||||
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
|
||||
3
src/main/resources/version.properties
Normal file
3
src/main/resources/version.properties
Normal file
@@ -0,0 +1,3 @@
|
||||
version=${project.version}
|
||||
groupId=${project.groupId}
|
||||
artifactId=${project.artifactId}
|
||||
Reference in New Issue
Block a user