mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-19 16:41:53 +00:00
Compare commits
72 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
314ae58ebd | ||
|
|
d8b6232ac1 | ||
|
|
41e22ee64d | ||
|
|
be2fbcd4cb | ||
|
|
14e7f37522 | ||
|
|
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 | ||
|
|
7c1d6e40b8 | ||
|
|
c5fbd5d1f0 | ||
|
|
aebde7ee48 | ||
|
|
c8fb93eeb6 | ||
|
|
1602ed004a | ||
|
|
7514e36edb | ||
|
|
2789d8c180 | ||
|
|
af1777aeb3 | ||
|
|
fc2d587e1a | ||
|
|
416b4d3fda | ||
|
|
9666273840 | ||
|
|
774bc8a36b | ||
|
|
74d4548beb | ||
|
|
eecf0f9875 | ||
|
|
ed96b5ad81 | ||
|
|
9f7d3ea331 | ||
|
|
68de92bb74 | ||
|
|
392a46c3d8 | ||
|
|
568569248a | ||
|
|
d61d10b5b6 | ||
|
|
7294dbf175 | ||
|
|
6c99358f95 | ||
|
|
eee0394f20 | ||
|
|
d87f3bc541 | ||
|
|
e38374f749 | ||
|
|
937fb5d32d | ||
|
|
bd60d63d0f | ||
|
|
439b081bd5 | ||
|
|
41f68f58b0 | ||
|
|
fa15cf3952 | ||
|
|
3ea7f2903f | ||
|
|
7746938c62 | ||
|
|
96074628fb | ||
|
|
9dc8d8f8bc | ||
|
|
8de39a8bee | ||
|
|
626f0641cc | ||
|
|
020da99e1c |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -9,3 +9,6 @@ buildNumber.properties
|
|||||||
data
|
data
|
||||||
.idea
|
.idea
|
||||||
/target/
|
/target/
|
||||||
|
/.settings/
|
||||||
|
/start.bat
|
||||||
|
/.classpath
|
||||||
|
|||||||
23
.project
Normal file
23
.project
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>ha-bridge</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
||||||
71
pom.xml
71
pom.xml
@@ -5,11 +5,11 @@
|
|||||||
|
|
||||||
<groupId>com.bwssystems.HABridge</groupId>
|
<groupId>com.bwssystems.HABridge</groupId>
|
||||||
<artifactId>ha-bridge</artifactId>
|
<artifactId>ha-bridge</artifactId>
|
||||||
<version>0.3.0</version>
|
<version>1.1.0</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>HA Bridge</name>
|
<name>HA Bridge</name>
|
||||||
<description>Emulates a Philips Hue bridge to allow the Amazon Echo to hook up to other HA systems, i.e. Vera, 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>
|
<properties>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
@@ -17,7 +17,19 @@
|
|||||||
<maven.compiler.target>1.8</maven.compiler.target>
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>jitpack.io</id>
|
||||||
|
<url>https://jitpack.io</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.bwssytems</groupId>
|
||||||
|
<artifactId>harmony-java-client</artifactId>
|
||||||
|
<version>1.0.8</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.sparkjava</groupId>
|
<groupId>com.sparkjava</groupId>
|
||||||
<artifactId>spark-core</artifactId>
|
<artifactId>spark-core</artifactId>
|
||||||
@@ -53,9 +65,40 @@
|
|||||||
<artifactId>json-io</artifactId>
|
<artifactId>json-io</artifactId>
|
||||||
<version>4.1.6</version>
|
<version>4.1.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.java.dev.eval</groupId>
|
||||||
|
<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>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<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>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
@@ -78,12 +121,12 @@
|
|||||||
<exclude>META-INF/*.RSA</exclude>
|
<exclude>META-INF/*.RSA</exclude>
|
||||||
<exclude>META-INF/*.txt</exclude>
|
<exclude>META-INF/*.txt</exclude>
|
||||||
<exclude>META-INF/maven/**</exclude>
|
<exclude>META-INF/maven/**</exclude>
|
||||||
<exclude>META-INF/services/**</exclude>
|
|
||||||
<exclude>META-INF/DEPENDENCIES</exclude>
|
|
||||||
<exclude>about_files/**</exclude>
|
<exclude>about_files/**</exclude>
|
||||||
<exclude>*.properties</exclude>
|
|
||||||
</excludes>
|
</excludes>
|
||||||
</filter>
|
</filter>
|
||||||
|
<filter>
|
||||||
|
<artifact>*:*</artifact>
|
||||||
|
</filter>
|
||||||
<filter>
|
<filter>
|
||||||
<artifact>org.slf4j:*</artifact>
|
<artifact>org.slf4j:*</artifact>
|
||||||
<includes>
|
<includes>
|
||||||
@@ -96,6 +139,24 @@
|
|||||||
<include>**</include>
|
<include>**</include>
|
||||||
</includes>
|
</includes>
|
||||||
</filter>
|
</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>
|
</filters>
|
||||||
<transformers>
|
<transformers>
|
||||||
<transformer
|
<transformer
|
||||||
|
|||||||
@@ -6,6 +6,12 @@ public class BridgeSettings {
|
|||||||
private String upnpresponseport;
|
private String upnpresponseport;
|
||||||
private String upnpdevicedb;
|
private String upnpdevicedb;
|
||||||
private String veraaddress;
|
private String veraaddress;
|
||||||
|
private String harmonyaddress;
|
||||||
|
private String harmonyuser;
|
||||||
|
private String harmonypwd;
|
||||||
|
private boolean upnpstrict;
|
||||||
|
private boolean traceupnp;
|
||||||
|
private boolean devmode;
|
||||||
|
|
||||||
public String getUpnpConfigAddress() {
|
public String getUpnpConfigAddress() {
|
||||||
return upnpconfigaddress;
|
return upnpconfigaddress;
|
||||||
@@ -37,6 +43,54 @@ public class BridgeSettings {
|
|||||||
public void setVeraAddress(String veraAddress) {
|
public void setVeraAddress(String veraAddress) {
|
||||||
this.veraaddress = 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;
|
||||||
|
}
|
||||||
|
public void setUpnpStrict(boolean upnpStrict) {
|
||||||
|
this.upnpstrict = upnpStrict;
|
||||||
|
}
|
||||||
|
public boolean isTraceupnp() {
|
||||||
|
return traceupnp;
|
||||||
|
}
|
||||||
|
public void setTraceupnp(boolean traceupnp) {
|
||||||
|
this.traceupnp = traceupnp;
|
||||||
|
}
|
||||||
|
public boolean isDevMode() {
|
||||||
|
return devmode;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/main/java/com/bwssystems/HABridge/Configuration.java
Normal file
11
src/main/java/com/bwssystems/HABridge/Configuration.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package com.bwssystems.HABridge;
|
||||||
|
|
||||||
|
public class Configuration {
|
||||||
|
public final static String DEVICE_DB_DIRECTORY = "data/device.db";
|
||||||
|
public final static String UPNP_RESPONSE_PORT = "50000";
|
||||||
|
public final static String 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,7 +12,7 @@ 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.vera.VeraInfo;
|
import com.bwssystems.harmony.HarmonyServer;
|
||||||
|
|
||||||
public class HABridge {
|
public class HABridge {
|
||||||
|
|
||||||
@@ -34,13 +34,18 @@ 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;
|
||||||
HueMulator theHueMulator;
|
HueMulator theHueMulator;
|
||||||
UpnpSettingsResource theSettingResponder;
|
UpnpSettingsResource theSettingResponder;
|
||||||
UpnpListener theUpnpListener;
|
UpnpListener theUpnpListener;
|
||||||
InetAddress address;
|
InetAddress address;
|
||||||
String addressString;
|
String addressString;
|
||||||
BridgeSettings bridgeSettings;
|
BridgeSettings bridgeSettings;
|
||||||
|
Version theVersion;
|
||||||
|
|
||||||
|
theVersion = new Version();
|
||||||
|
|
||||||
|
log.info("HA Bridge (v" + theVersion.getVersion() + ") starting setup....");
|
||||||
//get ip address for upnp requests
|
//get ip address for upnp requests
|
||||||
try {
|
try {
|
||||||
address = InetAddress.getLocalHost();
|
address = InetAddress.getLocalHost();
|
||||||
@@ -51,31 +56,44 @@ public class HABridge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bridgeSettings = new BridgeSettings();
|
bridgeSettings = new BridgeSettings();
|
||||||
|
bridgeSettings.setServerPort(System.getProperty("server.port", Configuration.DFAULT_WEB_PORT));
|
||||||
bridgeSettings.setUpnpConfigAddress(System.getProperty("upnp.config.address", addressString));
|
bridgeSettings.setUpnpConfigAddress(System.getProperty("upnp.config.address", addressString));
|
||||||
bridgeSettings.setUpnpDeviceDb(System.getProperty("upnp.device.db", "data/device.db"));
|
bridgeSettings.setUpnpDeviceDb(System.getProperty("upnp.device.db", Configuration.DEVICE_DB_DIRECTORY));
|
||||||
bridgeSettings.setUpnpResponsePort(System.getProperty("upnp.response.port", "50000"));
|
bridgeSettings.setUpnpResponsePort(System.getProperty("upnp.response.port", Configuration.UPNP_RESPONSE_PORT));
|
||||||
bridgeSettings.setVeraAddress(System.getProperty("vera.address", "192.168.1.100"));
|
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.setDevMode(Boolean.parseBoolean(System.getProperty("dev.mode", "false")));
|
||||||
|
|
||||||
// sparkjava config directive to set ip address for the web server to listen on
|
// sparkjava config directive to set ip address for the web server to listen on
|
||||||
// ipAddress("0.0.0.0"); // not used
|
// ipAddress("0.0.0.0"); // not used
|
||||||
// sparkjava config directive to set port for the web server to listen on
|
// sparkjava config directive to set port for the web server to listen on
|
||||||
bridgeSettings.setServerPort(System.getProperty("server.port", "8080"));
|
|
||||||
port(Integer.valueOf(bridgeSettings.getServerPort()));
|
port(Integer.valueOf(bridgeSettings.getServerPort()));
|
||||||
// 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");
|
||||||
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
|
// 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
|
// 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
|
// setup the class to handle the upnp response rest api
|
||||||
theSettingResponder = new UpnpSettingsResource(bridgeSettings);
|
theSettingResponder = new UpnpSettingsResource(bridgeSettings);
|
||||||
|
theSettingResponder.setupServer();
|
||||||
// wait for the sparkjava initialization of the rest api classes to be complete
|
// wait for the sparkjava initialization of the rest api classes to be complete
|
||||||
awaitInitialization();
|
awaitInitialization();
|
||||||
|
|
||||||
// start the upnp ssdp discovery listener
|
// start the upnp ssdp discovery listener
|
||||||
theUpnpListener = new UpnpListener(bridgeSettings);
|
theUpnpListener = new UpnpListener(bridgeSettings);
|
||||||
log.info("Done setup, application to run....");
|
|
||||||
theUpnpListener.startListening();
|
theUpnpListener.startListening();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
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,43 +0,0 @@
|
|||||||
package com.bwssystems.HABridge.api;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by arm on 4/13/15.
|
|
||||||
*/
|
|
||||||
public class Device {
|
|
||||||
private String name;
|
|
||||||
private String deviceType;
|
|
||||||
private String offUrl;
|
|
||||||
private String onUrl;
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDeviceType() {
|
|
||||||
return deviceType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDeviceType(String deviceType) {
|
|
||||||
this.deviceType = deviceType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOffUrl() {
|
|
||||||
return offUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOffUrl(String offUrl) {
|
|
||||||
this.offUrl = offUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOnUrl() {
|
|
||||||
return onUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOnUrl(String onUrl) {
|
|
||||||
this.onUrl = onUrl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.bwssystems.HABridge.api;
|
||||||
|
|
||||||
|
public class UserCreateRequest {
|
||||||
|
private String devicetype;
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
public String getDevicetype() {
|
||||||
|
return devicetype;
|
||||||
|
}
|
||||||
|
public void setDevicetype(String devicetype) {
|
||||||
|
this.devicetype = devicetype;
|
||||||
|
}
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,5 @@
|
|||||||
package com.bwssystems.HABridge.api.hue;
|
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.
|
* Created by arm on 4/14/15.
|
||||||
*/
|
*/
|
||||||
@@ -16,7 +11,6 @@ public class DeviceResponse {
|
|||||||
private String manufacturername;
|
private String manufacturername;
|
||||||
private String uniqueid;
|
private String uniqueid;
|
||||||
private String swversion;
|
private String swversion;
|
||||||
private Map<String, String> pointsymbol;
|
|
||||||
|
|
||||||
public DeviceState getState() {
|
public DeviceState getState() {
|
||||||
return state;
|
return state;
|
||||||
@@ -74,24 +68,6 @@ public class DeviceResponse {
|
|||||||
this.swversion = swversion;
|
this.swversion = swversion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getPointsymbol() {
|
|
||||||
Map<String, String> dummyValue = new HashMap<>();
|
|
||||||
dummyValue.put("1", "none");
|
|
||||||
dummyValue.put("2", "none");
|
|
||||||
dummyValue.put("3", "none");
|
|
||||||
dummyValue.put("4", "none");
|
|
||||||
dummyValue.put("5", "none");
|
|
||||||
dummyValue.put("6", "none");
|
|
||||||
dummyValue.put("7", "none");
|
|
||||||
dummyValue.put("8", "none");
|
|
||||||
|
|
||||||
return dummyValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPointsymbol(Map<String, String> pointsymbol) {
|
|
||||||
this.pointsymbol = pointsymbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DeviceResponse createResponse(String name, String id){
|
public static DeviceResponse createResponse(String name, String id){
|
||||||
DeviceState deviceState = new DeviceState();
|
DeviceState deviceState = new DeviceState();
|
||||||
DeviceResponse response = new DeviceResponse();
|
DeviceResponse response = new DeviceResponse();
|
||||||
@@ -101,21 +77,13 @@ public class DeviceResponse {
|
|||||||
deviceState.setEffect("none");
|
deviceState.setEffect("none");
|
||||||
deviceState.setAlert("none");
|
deviceState.setAlert("none");
|
||||||
deviceState.setBri(254);
|
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.setName(name);
|
||||||
response.setUniqueid(id);
|
response.setUniqueid(id);
|
||||||
response.setManufacturername("Philips");
|
response.setManufacturername("Philips");
|
||||||
response.setType("Extended color light");
|
response.setType("Dimmable light");
|
||||||
response.setModelid("LCT001");
|
response.setModelid("LWB004");
|
||||||
response.setSwversion("65003148");
|
response.setSwversion("66012040");
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.bwssystems.HABridge.api.hue;
|
package com.bwssystems.HABridge.api.hue;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by arm on 4/14/15.
|
* Created by arm on 4/14/15.
|
||||||
@@ -8,14 +7,9 @@ import java.util.List;
|
|||||||
public class DeviceState {
|
public class DeviceState {
|
||||||
private boolean on;
|
private boolean on;
|
||||||
private int bri = 255;
|
private int bri = 255;
|
||||||
private int hue;
|
|
||||||
private int sat;
|
|
||||||
private String effect;
|
private String effect;
|
||||||
private int ct;
|
|
||||||
private String alert;
|
private String alert;
|
||||||
private String colormode;
|
|
||||||
private boolean reachable;
|
private boolean reachable;
|
||||||
private List<Double> xy;
|
|
||||||
|
|
||||||
public boolean isOn() {
|
public boolean isOn() {
|
||||||
return on;
|
return on;
|
||||||
@@ -33,22 +27,6 @@ public class DeviceState {
|
|||||||
this.bri = bri;
|
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() {
|
public String getEffect() {
|
||||||
return effect;
|
return effect;
|
||||||
}
|
}
|
||||||
@@ -57,14 +35,6 @@ public class DeviceState {
|
|||||||
this.effect = effect;
|
this.effect = effect;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCt() {
|
|
||||||
return ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCt(int ct) {
|
|
||||||
this.ct = ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAlert() {
|
public String getAlert() {
|
||||||
return alert;
|
return alert;
|
||||||
}
|
}
|
||||||
@@ -73,14 +43,6 @@ public class DeviceState {
|
|||||||
this.alert = alert;
|
this.alert = alert;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getColormode() {
|
|
||||||
return colormode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColormode(String colormode) {
|
|
||||||
this.colormode = colormode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isReachable() {
|
public boolean isReachable() {
|
||||||
return reachable;
|
return reachable;
|
||||||
}
|
}
|
||||||
@@ -89,14 +51,6 @@ public class DeviceState {
|
|||||||
this.reachable = reachable;
|
this.reachable = reachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Double> getXy() {
|
|
||||||
return xy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setXy(List<Double> xy) {
|
|
||||||
this.xy = xy;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "DeviceState{" +
|
return "DeviceState{" +
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.bwssystems.HABridge.api.hue;
|
package com.bwssystems.HABridge.api.hue;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
||||||
@@ -9,6 +10,16 @@ import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
|||||||
*/
|
*/
|
||||||
public class HueApiResponse {
|
public class HueApiResponse {
|
||||||
private Map<String, DeviceResponse> lights;
|
private Map<String, DeviceResponse> lights;
|
||||||
|
private Map<String, String> scenes;
|
||||||
|
private Map<String, String> groups;
|
||||||
|
private HueConfig config;
|
||||||
|
|
||||||
|
public HueApiResponse(String name, String ipaddress, String devicetype, String userid) {
|
||||||
|
super();
|
||||||
|
this.setConfig(HueConfig.createConfig(name, ipaddress, devicetype, userid));
|
||||||
|
this.setGroups(new HashMap<>());
|
||||||
|
this.setScenes(new HashMap<>());
|
||||||
|
}
|
||||||
|
|
||||||
public Map<String, DeviceResponse> getLights() {
|
public Map<String, DeviceResponse> getLights() {
|
||||||
return lights;
|
return lights;
|
||||||
@@ -17,4 +28,28 @@ public class HueApiResponse {
|
|||||||
public void setLights(Map<String, DeviceResponse> lights) {
|
public void setLights(Map<String, DeviceResponse> lights) {
|
||||||
this.lights = lights;
|
this.lights = lights;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getScenes() {
|
||||||
|
return scenes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScenes(Map<String, String> scenes) {
|
||||||
|
this.scenes = scenes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getGroups() {
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroups(Map<String, String> groups) {
|
||||||
|
this.groups = groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HueConfig getConfig() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfig(HueConfig config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
234
src/main/java/com/bwssystems/HABridge/api/hue/HueConfig.java
Normal file
234
src/main/java/com/bwssystems/HABridge/api/hue/HueConfig.java
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
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.Map;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
public class HueConfig
|
||||||
|
{
|
||||||
|
private Boolean portalservices;
|
||||||
|
private String gateway;
|
||||||
|
private String mac;
|
||||||
|
private String swversion;
|
||||||
|
private String apiversion;
|
||||||
|
private Boolean linkbutton;
|
||||||
|
private String ipaddress;
|
||||||
|
private Integer proxyport;
|
||||||
|
private Swupdate swupdate;
|
||||||
|
private String netmask;
|
||||||
|
private String name;
|
||||||
|
private Boolean dhcp;
|
||||||
|
private String UTC;
|
||||||
|
private String proxyaddress;
|
||||||
|
private String localtime;
|
||||||
|
private String timezone;
|
||||||
|
private String zigbeechannel;
|
||||||
|
private Map<String, WhitelistEntry> whitelist;
|
||||||
|
|
||||||
|
public static HueConfig createConfig(String name, String ipaddress, String devicetype, String userid) {
|
||||||
|
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.setPortalservices(false);
|
||||||
|
aConfig.setGateway(ipaddress);
|
||||||
|
aConfig.setSwversion("01005215");
|
||||||
|
aConfig.setLinkbutton(false);
|
||||||
|
aConfig.setIpaddress(ipaddress);
|
||||||
|
aConfig.setProxyport(0);
|
||||||
|
aConfig.setSwupdate(Swupdate.createSwupdate());
|
||||||
|
aConfig.setNetmask("255.255.255.0");
|
||||||
|
aConfig.setName(name);
|
||||||
|
aConfig.setDhcp(true);
|
||||||
|
aConfig.setUtc(dateFormatGmt.format(new Date()));
|
||||||
|
aConfig.setProxyaddress("none");
|
||||||
|
aConfig.setLocaltime(dateFormat.format(new Date()));
|
||||||
|
aConfig.setTimezone(TimeZone.getDefault().getID());
|
||||||
|
aConfig.setZigbeechannel("6");
|
||||||
|
Map<String, WhitelistEntry> awhitelist = new HashMap<>();
|
||||||
|
awhitelist.put(userid, WhitelistEntry.createEntry(devicetype));
|
||||||
|
aConfig.setWhitelist(awhitelist);
|
||||||
|
|
||||||
|
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() {
|
||||||
|
return portalservices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPortalservices(Boolean portalservices) {
|
||||||
|
this.portalservices = portalservices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGateway() {
|
||||||
|
return gateway;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGateway(String gateway) {
|
||||||
|
this.gateway = gateway;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMac() {
|
||||||
|
return mac;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMac(String mac) {
|
||||||
|
this.mac = mac;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSwversion() {
|
||||||
|
return swversion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSwversion(String swversion) {
|
||||||
|
this.swversion = swversion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getLinkbutton() {
|
||||||
|
return linkbutton;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLinkbutton(Boolean linkbutton) {
|
||||||
|
this.linkbutton = linkbutton;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIpaddress() {
|
||||||
|
return ipaddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIpaddress(String ipaddress) {
|
||||||
|
this.ipaddress = ipaddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getProxyport() {
|
||||||
|
return proxyport;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProxyport(Integer proxyport) {
|
||||||
|
this.proxyport = proxyport;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Swupdate getSwupdate() {
|
||||||
|
return swupdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSwupdate(Swupdate swupdate) {
|
||||||
|
this.swupdate = swupdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNetmask() {
|
||||||
|
return netmask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNetmask(String netmask) {
|
||||||
|
this.netmask = netmask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getDhcp() {
|
||||||
|
return dhcp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDhcp(Boolean dhcp) {
|
||||||
|
this.dhcp = dhcp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUtc() {
|
||||||
|
return UTC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUtc(String utc) {
|
||||||
|
this.UTC = utc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProxyaddress() {
|
||||||
|
return proxyaddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProxyaddress(String proxyaddress) {
|
||||||
|
this.proxyaddress = proxyaddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, WhitelistEntry> getWhitelist() {
|
||||||
|
return whitelist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWhitelist(Map<String, WhitelistEntry> whitelist) {
|
||||||
|
this.whitelist = whitelist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getApiversion() {
|
||||||
|
return apiversion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApiversion(String apiversion) {
|
||||||
|
this.apiversion = apiversion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLocaltime() {
|
||||||
|
return localtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocaltime(String localtime) {
|
||||||
|
this.localtime = localtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTimezone() {
|
||||||
|
return timezone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimezone(String timezone) {
|
||||||
|
this.timezone = timezone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getZigbeechannel() {
|
||||||
|
return zigbeechannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZigbeechannel(String zigbeechannel) {
|
||||||
|
this.zigbeechannel = zigbeechannel;
|
||||||
|
}
|
||||||
|
}
|
||||||
52
src/main/java/com/bwssystems/HABridge/api/hue/Swupdate.java
Normal file
52
src/main/java/com/bwssystems/HABridge/api/hue/Swupdate.java
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package com.bwssystems.HABridge.api.hue;
|
||||||
|
|
||||||
|
|
||||||
|
public class Swupdate
|
||||||
|
{
|
||||||
|
private String text;
|
||||||
|
private Boolean notify;
|
||||||
|
private Integer updatestate;
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
public static Swupdate createSwupdate() {
|
||||||
|
Swupdate aSwupdate = new Swupdate();
|
||||||
|
aSwupdate.setNotify(false);
|
||||||
|
aSwupdate.setText("");
|
||||||
|
aSwupdate.setUpdatestate(0);
|
||||||
|
aSwupdate.setUrl("");
|
||||||
|
return aSwupdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText(String text) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getNotify() {
|
||||||
|
return notify;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNotify(Boolean notify) {
|
||||||
|
this.notify = notify;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getUpdatestate() {
|
||||||
|
return updatestate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdatestate(Integer updatestate) {
|
||||||
|
this.updatestate = updatestate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.bwssystems.HABridge.api.hue;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class WhitelistEntry
|
||||||
|
{
|
||||||
|
private String lastUseDate;
|
||||||
|
private String createDate;
|
||||||
|
private String name;
|
||||||
|
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||||
|
|
||||||
|
public static WhitelistEntry createEntry(String devicetype) {
|
||||||
|
WhitelistEntry anEntry = new WhitelistEntry();
|
||||||
|
anEntry.setName(devicetype);
|
||||||
|
anEntry.setCreateDate(getCurrentDate());
|
||||||
|
anEntry.setLastUseDate(getCurrentDate());
|
||||||
|
return anEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getCurrentDate() {
|
||||||
|
return dateFormat.format(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastUseDate() {
|
||||||
|
return lastUseDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastUseDate(String lastUseDate) {
|
||||||
|
this.lastUseDate = lastUseDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreateDate() {
|
||||||
|
return createDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateDate(String createDate) {
|
||||||
|
this.createDate = createDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,9 +5,15 @@ 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 offUrl;
|
private String offUrl;
|
||||||
private String onUrl;
|
private String onUrl;
|
||||||
|
private String httpVerb;
|
||||||
|
private String contentType;
|
||||||
|
private String contentBody;
|
||||||
|
private String contentBodyOff;
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
@@ -17,6 +23,22 @@ public class DeviceDescriptor{
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
public String getDeviceType() {
|
||||||
return deviceType;
|
return deviceType;
|
||||||
}
|
}
|
||||||
@@ -48,4 +70,38 @@ public class DeviceDescriptor{
|
|||||||
public void setId(String id) {
|
public void setId(String id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getHttpVerb() {
|
||||||
|
return httpVerb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHttpVerb(String httpVerb) {
|
||||||
|
this.httpVerb = httpVerb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContentType() {
|
||||||
|
return contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentType(String contentType) {
|
||||||
|
this.contentType = contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContentBody() {
|
||||||
|
return contentBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentBody(String contentBody) {
|
||||||
|
this.contentBody = contentBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContentBodyOff() {
|
||||||
|
return contentBodyOff;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentBodyOff(String contentBodyOff) {
|
||||||
|
this.contentBodyOff = contentBodyOff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.bwssystems.HABridge.dao;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
import java.nio.file.FileSystems;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
@@ -43,7 +44,7 @@ public class DeviceRepository {
|
|||||||
DeviceDescriptor theDevice = null;
|
DeviceDescriptor theDevice = null;
|
||||||
while (theIterator.hasNext()) {
|
while (theIterator.hasNext()) {
|
||||||
theDevice = theIterator.next();
|
theDevice = theIterator.next();
|
||||||
put(Integer.parseInt(theDevice.getId()), theDevice);
|
put(theDevice.getId(), theDevice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,20 +63,20 @@ public class DeviceRepository {
|
|||||||
return devices.get(id);
|
return devices.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void put(int id, DeviceDescriptor aDescriptor) {
|
private void put(String id, DeviceDescriptor aDescriptor) {
|
||||||
devices.put(String.valueOf(id), aDescriptor);
|
devices.put(id, aDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save(DeviceDescriptor aDescriptor) {
|
public void save(DeviceDescriptor aDescriptor) {
|
||||||
int id = random.nextInt(Integer.MAX_VALUE);
|
|
||||||
if(aDescriptor.getId() != null)
|
if(aDescriptor.getId() != null)
|
||||||
devices.remove(aDescriptor.getId());
|
devices.remove(aDescriptor.getId());
|
||||||
else
|
else
|
||||||
aDescriptor.setId(String.valueOf(id));
|
aDescriptor.setId(String.valueOf(random.nextInt(Integer.MAX_VALUE)));
|
||||||
put(id, aDescriptor);
|
put(aDescriptor.getId(), aDescriptor);
|
||||||
JsonTransformer aRenderer = new JsonTransformer();
|
JsonTransformer aRenderer = new JsonTransformer();
|
||||||
String jsonValue = aRenderer.render(findAll());
|
String jsonValue = aRenderer.render(findAll());
|
||||||
repositoryWriter(jsonValue, repositoryPath);
|
repositoryWriter(jsonValue, repositoryPath);
|
||||||
|
log.debug("Save device: " + aDescriptor.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String delete(DeviceDescriptor aDescriptor) {
|
public String delete(DeviceDescriptor aDescriptor) {
|
||||||
@@ -106,7 +107,14 @@ public class DeviceRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
Path target = null;
|
||||||
|
if(Files.exists(filePath)) {
|
||||||
|
target = FileSystems.getDefault().getPath(filePath.getParent().toString(), "device.db.old");
|
||||||
|
Files.move(filePath, target);
|
||||||
|
}
|
||||||
Files.write(filePath, content.getBytes(), StandardOpenOption.CREATE);
|
Files.write(filePath, content.getBytes(), StandardOpenOption.CREATE);
|
||||||
|
if(target != null)
|
||||||
|
Files.delete(target);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("Error writing the file: " + filePath + " message: " + e.getMessage(), e);
|
log.error("Error writing the file: " + filePath + " message: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
@@ -116,7 +124,7 @@ public class DeviceRepository {
|
|||||||
|
|
||||||
String content = null;
|
String content = null;
|
||||||
if(Files.notExists(filePath) || !Files.isReadable(filePath)){
|
if(Files.notExists(filePath) || !Files.isReadable(filePath)){
|
||||||
log.error("Error reading the file: " + filePath + " - Does not exist or is not readable. ");
|
log.warn("Error reading the file: " + filePath + " - Does not exist or is not readable. continuing...");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,6 +178,12 @@ 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());
|
||||||
@@ -179,6 +193,18 @@ public class DeviceRepository {
|
|||||||
} else if (name.equals("onUrl")) {
|
} else if (name.equals("onUrl")) {
|
||||||
deviceEntry.setOnUrl(reader.nextString());
|
deviceEntry.setOnUrl(reader.nextString());
|
||||||
log.debug("Read a Device - device json on URL:" + deviceEntry.getOnUrl());
|
log.debug("Read a Device - device json on URL:" + deviceEntry.getOnUrl());
|
||||||
|
} else if (name.equals("httpVerb")) {
|
||||||
|
deviceEntry.setHttpVerb(reader.nextString());
|
||||||
|
log.debug("Read a Device - device json httpVerb:" + deviceEntry.getHttpVerb());
|
||||||
|
} else if (name.equals("contentType")) {
|
||||||
|
deviceEntry.setContentType(reader.nextString());
|
||||||
|
log.debug("Read a Device - device json contentType:" + deviceEntry.getContentType());
|
||||||
|
} else if (name.equals("contentBody")) {
|
||||||
|
deviceEntry.setContentBody(reader.nextString());
|
||||||
|
log.debug("Read a Device - device json contentBody:" + deviceEntry.getContentBody());
|
||||||
|
} else if (name.equals("contentBodyOff")) {
|
||||||
|
deviceEntry.setContentBodyOff(reader.nextString());
|
||||||
|
log.debug("Read a Device - device json contentBodyOff:" + deviceEntry.getContentBodyOff());
|
||||||
} else {
|
} else {
|
||||||
reader.skipValue();
|
reader.skipValue();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,26 @@
|
|||||||
package com.bwssystems.HABridge.devicemanagmeent;
|
package com.bwssystems.HABridge.devicemanagmeent;
|
||||||
|
|
||||||
import static spark.Spark.get;
|
import static spark.Spark.get;
|
||||||
|
import static spark.Spark.options;
|
||||||
import static spark.Spark.post;
|
import static spark.Spark.post;
|
||||||
import static spark.Spark.put;
|
import static spark.Spark.put;
|
||||||
import static spark.Spark.delete;
|
import static spark.Spark.delete;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
import org.slf4j.Logger;
|
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.JsonTransformer;
|
import com.bwssystems.HABridge.JsonTransformer;
|
||||||
|
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.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;
|
||||||
@@ -27,12 +34,16 @@ public class DeviceResource {
|
|||||||
|
|
||||||
private DeviceRepository deviceRepository;
|
private DeviceRepository deviceRepository;
|
||||||
private VeraInfo veraInfo;
|
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, Version theVersion, HarmonyHandler myHarmony) {
|
||||||
public DeviceResource(BridgeSettings theSettings) {
|
|
||||||
super();
|
super();
|
||||||
deviceRepository = new DeviceRepository(theSettings.getUpnpDeviceDb());
|
this.deviceRepository = new DeviceRepository(theSettings.getUpnpDeviceDb());
|
||||||
veraInfo = new VeraInfo(theSettings.getVeraAddress());
|
this.veraInfo = new VeraInfo(theSettings.getVeraAddress(), theSettings.isValidVera());
|
||||||
|
this.myHarmonyHandler = myHarmony;
|
||||||
|
this.version = theVersion;
|
||||||
setupEndpoints();
|
setupEndpoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,41 +52,73 @@ public class DeviceResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupEndpoints() {
|
private void setupEndpoints() {
|
||||||
log.debug("Setting up endpoints");
|
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) -> {
|
post(API_CONTEXT, "application/json", (request, response) -> {
|
||||||
log.debug("Create a Device - request body: " + request.body());
|
log.debug("Create a Device - request body: " + request.body());
|
||||||
DeviceDescriptor device = new Gson().fromJson(request.body(), DeviceDescriptor.class);
|
DeviceDescriptor device = new Gson().fromJson(request.body(), DeviceDescriptor.class);
|
||||||
DeviceDescriptor deviceEntry = new DeviceDescriptor();
|
if(device.getContentBody() != null ) {
|
||||||
deviceEntry.setName(device.getName());
|
if (device.getContentType() == null || device.getHttpVerb() == null || !supportedVerbs.contains(device.getHttpVerb().toLowerCase())) {
|
||||||
log.debug("Create a Device - device json name: " + deviceEntry.getName());
|
device = null;
|
||||||
deviceEntry.setDeviceType(device.getDeviceType());
|
response.status(HttpStatus.SC_BAD_REQUEST);
|
||||||
log.debug("Create a Device - device json type:" + deviceEntry.getDeviceType());
|
log.debug("Bad http verb in create a Device: " + request.body());
|
||||||
deviceEntry.setOnUrl(device.getOnUrl());
|
return device;
|
||||||
log.debug("Create a Device - device json on URL:" + deviceEntry.getOnUrl());
|
}
|
||||||
deviceEntry.setOffUrl(device.getOffUrl());
|
}
|
||||||
log.debug("Create a Device - device json off URL:" + deviceEntry.getOffUrl());
|
|
||||||
|
|
||||||
deviceRepository.save(deviceEntry);
|
deviceRepository.save(device);
|
||||||
log.debug("Created a Device");
|
log.debug("Created a Device: " + request.body());
|
||||||
|
|
||||||
response.status(201);
|
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||||
return deviceEntry;
|
response.status(HttpStatus.SC_CREATED);
|
||||||
|
|
||||||
|
return device;
|
||||||
}, new JsonTransformer());
|
}, 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) -> {
|
put (API_CONTEXT + "/:id", "application/json", (request, response) -> {
|
||||||
log.debug("Saved a Device");
|
log.debug("Edit a Device - request body: " + request.body());
|
||||||
DeviceDescriptor device = new Gson().fromJson(request.body(), DeviceDescriptor.class);
|
DeviceDescriptor device = new Gson().fromJson(request.body(), DeviceDescriptor.class);
|
||||||
DeviceDescriptor deviceEntry = deviceRepository.findOne(request.params(":id"));
|
DeviceDescriptor deviceEntry = deviceRepository.findOne(request.params(":id"));
|
||||||
if(deviceEntry == null){
|
if(deviceEntry == null){
|
||||||
return null;
|
log.debug("Could not save an edited Device Id: " + request.params(":id"));
|
||||||
|
response.status(HttpStatus.SC_BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.debug("Saving an edited Device: " + deviceEntry.getName());
|
||||||
|
|
||||||
deviceEntry.setName(device.getName());
|
deviceEntry.setName(device.getName());
|
||||||
|
if (device.getDeviceType() != null)
|
||||||
deviceEntry.setDeviceType(device.getDeviceType());
|
deviceEntry.setDeviceType(device.getDeviceType());
|
||||||
|
deviceEntry.setMapId(device.getMapId());
|
||||||
|
deviceEntry.setMapType(device.getMapType());
|
||||||
deviceEntry.setOnUrl(device.getOnUrl());
|
deviceEntry.setOnUrl(device.getOnUrl());
|
||||||
deviceEntry.setOffUrl(device.getOffUrl());
|
deviceEntry.setOffUrl(device.getOffUrl());
|
||||||
|
deviceEntry.setHttpVerb(device.getHttpVerb());
|
||||||
|
deviceEntry.setContentType(device.getContentType());
|
||||||
|
deviceEntry.setContentBody(device.getContentBody());
|
||||||
|
deviceEntry.setContentBodyOff(device.getContentBodyOff());
|
||||||
|
|
||||||
deviceRepository.save(deviceEntry);
|
deviceRepository.save(deviceEntry);
|
||||||
|
response.status(HttpStatus.SC_OK);
|
||||||
|
}
|
||||||
return deviceEntry;
|
return deviceEntry;
|
||||||
}, new JsonTransformer());
|
}, new JsonTransformer());
|
||||||
|
|
||||||
@@ -85,34 +128,49 @@ public class DeviceResource {
|
|||||||
JsonTransformer aRenderer = new JsonTransformer();
|
JsonTransformer aRenderer = new JsonTransformer();
|
||||||
String theStream = aRenderer.render(deviceList);
|
String theStream = aRenderer.render(deviceList);
|
||||||
log.debug("The Device List: " + theStream);
|
log.debug("The Device List: " + theStream);
|
||||||
|
response.status(HttpStatus.SC_OK);
|
||||||
return deviceList;
|
return deviceList;
|
||||||
}, new JsonTransformer());
|
}, new JsonTransformer());
|
||||||
|
|
||||||
get (API_CONTEXT + "/:id", "application/json", (request, response) -> {
|
get (API_CONTEXT + "/:id", "application/json", (request, response) -> {
|
||||||
log.debug("Get a device");
|
log.debug("Get a device");
|
||||||
DeviceDescriptor descriptor = deviceRepository.findOne(request.params(":id"));
|
DeviceDescriptor descriptor = deviceRepository.findOne(request.params(":id"));
|
||||||
if(descriptor == null){
|
if(descriptor == null)
|
||||||
return null;
|
response.status(HttpStatus.SC_NOT_FOUND);
|
||||||
}
|
else
|
||||||
|
response.status(HttpStatus.SC_OK);
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}, 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);
|
||||||
if(deleted == null){
|
DeviceDescriptor deleted = deviceRepository.findOne(anId);
|
||||||
return null;
|
if(deleted == null)
|
||||||
}
|
response.status(HttpStatus.SC_NOT_FOUND);
|
||||||
|
else
|
||||||
|
{
|
||||||
deviceRepository.delete(deleted);
|
deviceRepository.delete(deleted);
|
||||||
|
response.status(HttpStatus.SC_OK);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}, new JsonTransformer());
|
}, 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) -> {
|
get (API_CONTEXT + "/vera/devices", "application/json", (request, response) -> {
|
||||||
log.debug("Get vera devices");
|
log.debug("Get vera devices");
|
||||||
Sdata sData = veraInfo.getSdata();
|
Sdata sData = veraInfo.getSdata();
|
||||||
if(sData == null){
|
if(sData == null){
|
||||||
|
response.status(HttpStatus.SC_NOT_FOUND);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
response.status(HttpStatus.SC_OK);
|
||||||
return sData.getDevices();
|
return sData.getDevices();
|
||||||
}, new JsonTransformer());
|
}, new JsonTransformer());
|
||||||
|
|
||||||
@@ -120,10 +178,42 @@ public class DeviceResource {
|
|||||||
log.debug("Get vera scenes");
|
log.debug("Get vera scenes");
|
||||||
Sdata sData = veraInfo.getSdata();
|
Sdata sData = veraInfo.getSdata();
|
||||||
if(sData == null){
|
if(sData == null){
|
||||||
|
response.status(HttpStatus.SC_NOT_FOUND);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
response.status(HttpStatus.SC_OK);
|
||||||
return sData.getScenes();
|
return sData.getScenes();
|
||||||
}, new JsonTransformer());
|
}, 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());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,20 +1,34 @@
|
|||||||
package com.bwssystems.HABridge.hue;
|
package com.bwssystems.HABridge.hue;
|
||||||
|
|
||||||
import com.bwssystems.HABridge.JsonTransformer;
|
import com.bwssystems.HABridge.JsonTransformer;
|
||||||
|
import com.bwssystems.HABridge.api.UserCreateRequest;
|
||||||
import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
||||||
import com.bwssystems.HABridge.api.hue.DeviceState;
|
import com.bwssystems.HABridge.api.hue.DeviceState;
|
||||||
import com.bwssystems.HABridge.api.hue.HueApiResponse;
|
import com.bwssystems.HABridge.api.hue.HueApiResponse;
|
||||||
import com.bwssystems.HABridge.dao.*;
|
import com.bwssystems.HABridge.dao.*;
|
||||||
|
import com.bwssystems.harmony.ButtonPress;
|
||||||
|
import com.bwssystems.harmony.HarmonyHandler;
|
||||||
|
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;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
import net.java.dev.eval.Expression;
|
||||||
|
|
||||||
import static spark.Spark.get;
|
import static spark.Spark.get;
|
||||||
|
import static spark.Spark.options;
|
||||||
import static spark.Spark.post;
|
import static spark.Spark.post;
|
||||||
import static spark.Spark.put;
|
import static spark.Spark.put;
|
||||||
|
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
import org.apache.http.client.HttpClient;
|
import org.apache.http.client.HttpClient;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.client.methods.HttpPut;
|
||||||
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.impl.client.HttpClients;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
|
|
||||||
@@ -22,6 +36,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -34,52 +49,145 @@ public class HueMulator {
|
|||||||
private static final Logger log = LoggerFactory.getLogger(HueMulator.class);
|
private static final Logger log = LoggerFactory.getLogger(HueMulator.class);
|
||||||
private static final String INTENSITY_PERCENT = "${intensity.percent}";
|
private static final String INTENSITY_PERCENT = "${intensity.percent}";
|
||||||
private static final String INTENSITY_BYTE = "${intensity.byte}";
|
private static final String INTENSITY_BYTE = "${intensity.byte}";
|
||||||
|
private static final String INTENSITY_MATH = "${intensity.math(";
|
||||||
|
private static final String INTENSITY_MATH_VALUE = "X";
|
||||||
|
private static final String INTENSITY_MATH_CLOSE = ")}";
|
||||||
private static final String HUE_CONTEXT = "/api";
|
private static final String HUE_CONTEXT = "/api";
|
||||||
|
|
||||||
private DeviceRepository repository;
|
private DeviceRepository repository;
|
||||||
|
private HarmonyHandler myHarmony;
|
||||||
private HttpClient httpClient;
|
private HttpClient httpClient;
|
||||||
private ObjectMapper mapper;
|
private ObjectMapper mapper;
|
||||||
|
|
||||||
|
|
||||||
public HueMulator(DeviceRepository aDeviceRepository){
|
public HueMulator(DeviceRepository aDeviceRepository, HarmonyHandler theHandler){
|
||||||
httpClient = HttpClients.createMinimal();
|
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;
|
||||||
setupEndpoints();
|
myHarmony = theHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function sets up the sparkjava rest calls for the hue api
|
// This function sets up the sparkjava rest calls for the hue api
|
||||||
private void setupEndpoints() {
|
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) -> {
|
get(HUE_CONTEXT + "/:userid/lights", "application/json", (request, response) -> {
|
||||||
String userId = request.params(":userid");
|
String userId = request.params(":userid");
|
||||||
log.info("hue lights list requested: " + userId + " from " + request.ip());
|
log.debug("hue lights list requested: " + userId + " from " + request.ip());
|
||||||
List<DeviceDescriptor> deviceList = repository.findByDeviceType("switch");
|
List<DeviceDescriptor> deviceList = repository.findAll();
|
||||||
JsonTransformer aRenderer = new JsonTransformer();
|
Map<String, DeviceResponse> deviceResponseMap = new HashMap<>();
|
||||||
String theStream = aRenderer.render(deviceList);
|
|
||||||
log.debug("The Device List: " + theStream);
|
|
||||||
Map<String, String> deviceResponseMap = new HashMap<>();
|
|
||||||
for (DeviceDescriptor device : deviceList) {
|
for (DeviceDescriptor device : deviceList) {
|
||||||
deviceResponseMap.put(device.getId(), device.getName());
|
DeviceResponse deviceResponse = DeviceResponse.createResponse(device.getName(), device.getId());
|
||||||
|
deviceResponseMap.put(device.getId(), deviceResponse);
|
||||||
}
|
}
|
||||||
response.status(200);
|
response.type("application/json; charset=utf-8");
|
||||||
|
response.status(HttpStatus.SC_OK);
|
||||||
return deviceResponseMap;
|
return deviceResponseMap;
|
||||||
} , new JsonTransformer());
|
} , new JsonTransformer());
|
||||||
|
|
||||||
// http://ip_address:port/api/* returns json object for a test call
|
// http://ip_address:port/api CORS request
|
||||||
post(HUE_CONTEXT + "/*", "application/json", (request, response) -> {
|
options(HUE_CONTEXT, "application/json", (request, response) -> {
|
||||||
response.status(200);
|
response.status(HttpStatus.SC_OK);
|
||||||
return "[{\"success\":{\"username\":\"lights\"}}]";
|
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;
|
||||||
|
String aDeviceType = null;
|
||||||
|
|
||||||
|
log.debug("hue api user create requested: " + request.body() + " from " + request.ip());
|
||||||
|
|
||||||
|
if(request.body() != null && !request.body().isEmpty()) {
|
||||||
|
aNewUser = new Gson().fromJson(request.body(), UserCreateRequest.class);
|
||||||
|
newUser = aNewUser.getUsername();
|
||||||
|
aDeviceType = aNewUser.getDevicetype();
|
||||||
|
}
|
||||||
|
if(newUser == null)
|
||||||
|
newUser = "lightssystem";
|
||||||
|
|
||||||
|
if(aDeviceType == null)
|
||||||
|
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/{userId} returns json objects for the list of names of lights
|
// 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;
|
||||||
|
String newUser = null;
|
||||||
|
String aDeviceType = null;
|
||||||
|
|
||||||
|
log.info("HH trace: hue api user create requested: " + request.body() + " from " + request.ip());
|
||||||
|
|
||||||
|
if(request.body() != null && !request.body().isEmpty()) {
|
||||||
|
aNewUser = new Gson().fromJson(request.body(), UserCreateRequest.class);
|
||||||
|
newUser = aNewUser.getUsername();
|
||||||
|
aDeviceType = aNewUser.getDevicetype();
|
||||||
|
}
|
||||||
|
if(newUser == null)
|
||||||
|
newUser = "lightssystem";
|
||||||
|
|
||||||
|
if(aDeviceType == null)
|
||||||
|
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/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
|
||||||
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");
|
||||||
log.info("hue api root requested: " + userId + " from " + request.ip());
|
log.debug("hue api full state requested: " + userId + " from " + request.ip());
|
||||||
List<DeviceDescriptor> descriptorList = repository.findByDeviceType("switch");
|
List<DeviceDescriptor> descriptorList = repository.findAll();
|
||||||
if (descriptorList == null) {
|
if (descriptorList == null) {
|
||||||
response.status(404);
|
response.status(HttpStatus.SC_NOT_FOUND);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Map<String, DeviceResponse> deviceList = new HashMap<>();
|
Map<String, DeviceResponse> deviceList = new HashMap<>();
|
||||||
@@ -89,10 +197,11 @@ public class HueMulator {
|
|||||||
deviceList.put(descriptor.getId(), deviceResponse);
|
deviceList.put(descriptor.getId(), deviceResponse);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
HueApiResponse apiResponse = new HueApiResponse();
|
HueApiResponse apiResponse = new HueApiResponse("Philips hue", request.ip(), "My App", userId);
|
||||||
apiResponse.setLights(deviceList);
|
apiResponse.setLights(deviceList);
|
||||||
|
|
||||||
response.status(200);
|
response.type("application/json; charset=utf-8");
|
||||||
|
response.status(HttpStatus.SC_OK);
|
||||||
return apiResponse;
|
return apiResponse;
|
||||||
}, new JsonTransformer());
|
}, new JsonTransformer());
|
||||||
|
|
||||||
@@ -100,20 +209,30 @@ public class HueMulator {
|
|||||||
get(HUE_CONTEXT + "/:userid/lights/:id", "application/json", (request, response) -> {
|
get(HUE_CONTEXT + "/:userid/lights/:id", "application/json", (request, response) -> {
|
||||||
String userId = request.params(":userid");
|
String userId = request.params(":userid");
|
||||||
String lightId = request.params(":id");
|
String lightId = request.params(":id");
|
||||||
log.info("hue light requested: " + lightId + "for user: " + userId + " from " + request.ip());
|
log.debug("hue light requested: " + lightId + " for user: " + userId + " from " + request.ip());
|
||||||
DeviceDescriptor device = repository.findOne(lightId);
|
DeviceDescriptor device = repository.findOne(lightId);
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
response.status(404);
|
response.status(HttpStatus.SC_NOT_FOUND);
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
log.info("found device named: " + device.getName());
|
log.debug("found device named: " + device.getName());
|
||||||
}
|
}
|
||||||
DeviceResponse lightResponse = DeviceResponse.createResponse(device.getName(), device.getId());
|
DeviceResponse lightResponse = DeviceResponse.createResponse(device.getName(), device.getId());
|
||||||
|
|
||||||
response.status(200);
|
response.type("application/json; charset=utf-8");
|
||||||
|
response.status(HttpStatus.SC_OK);
|
||||||
return lightResponse;
|
return lightResponse;
|
||||||
}, new JsonTransformer());
|
}, new JsonTransformer());
|
||||||
|
|
||||||
|
// 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
|
// 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) -> {
|
put(HUE_CONTEXT + "/:userid/lights/:id/state", "application/json", (request, response) -> {
|
||||||
/**
|
/**
|
||||||
@@ -122,69 +241,147 @@ public class HueMulator {
|
|||||||
*/
|
*/
|
||||||
String userId = request.params(":userid");
|
String userId = request.params(":userid");
|
||||||
String lightId = request.params(":id");
|
String lightId = request.params(":id");
|
||||||
log.info("hue state change requested: " + userId + " from " + request.ip());
|
log.debug("hue state change requested: " + userId + " from " + request.ip() + " body: " + request.body());
|
||||||
log.info("hue stage change body: " + request.body() );
|
|
||||||
|
|
||||||
DeviceState state = null;
|
DeviceState state = null;
|
||||||
try {
|
try {
|
||||||
state = mapper.readValue(request.body(), DeviceState.class);
|
state = mapper.readValue(request.body(), DeviceState.class);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.info("object mapper barfed on input", e);
|
log.error("Object mapper barfed on input of body.", e);
|
||||||
response.status(400);
|
response.status(HttpStatus.SC_BAD_REQUEST);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceDescriptor device = repository.findOne(lightId);
|
DeviceDescriptor device = repository.findOne(lightId);
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
response.status(404);
|
response.status(HttpStatus.SC_NOT_FOUND);
|
||||||
|
log.error("Could not find devcie: " + lightId + " for hue state change request: " + userId + " from " + request.ip() + " body: " + request.body());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String responseString;
|
String responseString =null;
|
||||||
String url;
|
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();
|
||||||
} else {
|
} else if (request.body().contains("false")) {
|
||||||
responseString = "[{\"success\":{\"/lights/" + lightId + "/state/on\":false}}]";
|
responseString = "[{\"success\":{\"/lights/" + lightId + "/state/on\":false}}";
|
||||||
url = device.getOffUrl();
|
url = device.getOffUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/* light weight templating here, was going to use free marker but it was a bit too
|
/* light weight templating here, was going to use free marker but it was a bit too
|
||||||
* heavy for what we were trying to do.
|
* heavy for what we were trying to do.
|
||||||
*
|
*
|
||||||
* currently provides only two variables:
|
* currently provides:
|
||||||
* intensity.byte : 0-255 brightness. this is raw from the echo
|
* intensity.byte : 0-255 brightness. this is raw from the echo
|
||||||
* intensity.percent : 0-100, adjusted for the vera
|
* intensity.percent : 0-100, adjusted for the vera
|
||||||
|
* intensity.math(X*1) : where X is the value from the interface call and can use net.java.dev.eval math
|
||||||
*/
|
*/
|
||||||
if(url.contains(INTENSITY_BYTE)){
|
protected String replaceIntensityValue(String request, int intensity){
|
||||||
String intensityByte = String.valueOf(state.getBri());
|
if(request == null){
|
||||||
url = url.replace(INTENSITY_BYTE, intensityByte);
|
return "";
|
||||||
}else if(url.contains(INTENSITY_PERCENT)){
|
}
|
||||||
int percentBrightness = (int) Math.round(state.getBri()/255.0*100);
|
if(request.contains(INTENSITY_BYTE)){
|
||||||
|
String intensityByte = String.valueOf(intensity);
|
||||||
|
request = request.replace(INTENSITY_BYTE, intensityByte);
|
||||||
|
}else if(request.contains(INTENSITY_PERCENT)){
|
||||||
|
int percentBrightness = (int) Math.round(intensity/255.0*100);
|
||||||
String intensityPercent = String.valueOf(percentBrightness);
|
String intensityPercent = String.valueOf(percentBrightness);
|
||||||
url = url.replace(INTENSITY_PERCENT, intensityPercent);
|
request = request.replace(INTENSITY_PERCENT, intensityPercent);
|
||||||
|
} else if(request.contains(INTENSITY_MATH)){
|
||||||
|
Map<String, BigDecimal> variables = new HashMap<String, BigDecimal>();
|
||||||
|
String mathDescriptor = request.substring(request.indexOf(INTENSITY_MATH) + INTENSITY_MATH.length(),request.indexOf(INTENSITY_MATH_CLOSE));
|
||||||
|
variables.put(INTENSITY_MATH_VALUE, new BigDecimal(intensity));
|
||||||
|
|
||||||
|
try {
|
||||||
|
log.debug("Math eval is: " + mathDescriptor + ", Where " + INTENSITY_MATH_VALUE + " is: " + String.valueOf(intensity));
|
||||||
|
Expression exp = new Expression(mathDescriptor);
|
||||||
|
BigDecimal result = exp.eval(variables);
|
||||||
|
Integer endResult = Math.round(result.floatValue());
|
||||||
|
request = request.replace(INTENSITY_MATH + mathDescriptor + INTENSITY_MATH_CLOSE, endResult.toString());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Could not execute Math: " + mathDescriptor, e);
|
||||||
|
} }
|
||||||
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
//make call
|
|
||||||
if(!doHttpGETRequest(url)){
|
|
||||||
response.status(503);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
response.status(200);
|
|
||||||
return responseString;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function executes the url from the device repository against the vera
|
// This function executes the url from the device repository against the vera
|
||||||
protected boolean doHttpGETRequest(String url) {
|
protected boolean doHttpRequest(String url, String httpVerb, String contentType, String body) {
|
||||||
log.info("calling GET on URL: " + url);
|
HttpUriRequest request = null;
|
||||||
HttpGet httpGet = new HttpGet(url);
|
if(HttpGet.METHOD_NAME.equalsIgnoreCase(httpVerb) || httpVerb == null) {
|
||||||
|
request = new HttpGet(url);
|
||||||
|
}else if(HttpPost.METHOD_NAME.equalsIgnoreCase(httpVerb)){
|
||||||
|
HttpPost postRequest = new HttpPost(url);
|
||||||
|
ContentType parsedContentType = ContentType.parse(contentType);
|
||||||
|
StringEntity requestBody = new StringEntity(body, parsedContentType);
|
||||||
|
postRequest.setEntity(requestBody);
|
||||||
|
request = postRequest;
|
||||||
|
}else if(HttpPut.METHOD_NAME.equalsIgnoreCase(httpVerb)){
|
||||||
|
HttpPut putRequest = new HttpPut(url);
|
||||||
|
ContentType parsedContentType = ContentType.parse(contentType);
|
||||||
|
StringEntity requestBody = new StringEntity(body, parsedContentType);
|
||||||
|
putRequest.setEntity(requestBody);
|
||||||
|
request = putRequest;
|
||||||
|
}
|
||||||
|
log.debug("Making outbound call in doHttpRequest: " + request);
|
||||||
try {
|
try {
|
||||||
HttpResponse response = httpClient.execute(httpGet);
|
HttpResponse response = httpClient.execute(request);
|
||||||
EntityUtils.consume(response.getEntity()); //close out inputstream ignore content
|
EntityUtils.consume(response.getEntity()); //close out inputstream ignore content
|
||||||
log.info("GET on URL responded: " + response.getStatusLine().getStatusCode());
|
log.debug((httpVerb == null?"GET":httpVerb) + " execute on URL responded: " + response.getStatusLine().getStatusCode());
|
||||||
if(response.getStatusLine().getStatusCode() == 200){
|
if(response.getStatusLine().getStatusCode() == 200){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,15 +23,21 @@ public class UpnpListener {
|
|||||||
|
|
||||||
private String responseAddress;
|
private String responseAddress;
|
||||||
|
|
||||||
|
private boolean strict;
|
||||||
|
|
||||||
|
private boolean traceupnp;
|
||||||
|
|
||||||
public UpnpListener(BridgeSettings theSettings) {
|
public UpnpListener(BridgeSettings theSettings) {
|
||||||
super();
|
super();
|
||||||
upnpResponsePort = Integer.valueOf(theSettings.getUpnpResponsePort());
|
upnpResponsePort = Integer.valueOf(theSettings.getUpnpResponsePort());
|
||||||
httpServerPort = Integer.valueOf(theSettings.getServerPort());
|
httpServerPort = Integer.valueOf(theSettings.getServerPort());
|
||||||
responseAddress = theSettings.getUpnpConfigAddress();
|
responseAddress = theSettings.getUpnpConfigAddress();
|
||||||
|
strict = theSettings.isUpnpStrict();
|
||||||
|
traceupnp = theSettings.isTraceupnp();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startListening(){
|
public void startListening(){
|
||||||
log.info("Starting UPNP Discovery Listener");
|
log.info("UPNP Discovery Listener starting....");
|
||||||
|
|
||||||
try (DatagramSocket responseSocket = new DatagramSocket(upnpResponsePort);
|
try (DatagramSocket responseSocket = new DatagramSocket(upnpResponsePort);
|
||||||
MulticastSocket upnpMulticastSocket = new MulticastSocket(UPNP_DISCOVERY_PORT);) {
|
MulticastSocket upnpMulticastSocket = new MulticastSocket(UPNP_DISCOVERY_PORT);) {
|
||||||
@@ -46,6 +52,9 @@ public class UpnpListener {
|
|||||||
|
|
||||||
while (addrs.hasMoreElements()) {
|
while (addrs.hasMoreElements()) {
|
||||||
InetAddress addr = addrs.nextElement();
|
InetAddress addr = addrs.nextElement();
|
||||||
|
if(traceupnp)
|
||||||
|
log.info("Traceupnp: " + name + " ... has addr " + addr);
|
||||||
|
else
|
||||||
log.debug(name + " ... has addr " + addr);
|
log.debug(name + " ... has addr " + addr);
|
||||||
if (InetAddressUtils.isIPv4Address(addr.getHostAddress())) {
|
if (InetAddressUtils.isIPv4Address(addr.getHostAddress())) {
|
||||||
IPsPerNic++;
|
IPsPerNic++;
|
||||||
@@ -54,23 +63,26 @@ public class UpnpListener {
|
|||||||
log.debug("Checking " + name + " to our interface set");
|
log.debug("Checking " + name + " to our interface set");
|
||||||
if (IPsPerNic > 0) {
|
if (IPsPerNic > 0) {
|
||||||
upnpMulticastSocket.joinGroup(socketAddress, xface);
|
upnpMulticastSocket.joinGroup(socketAddress, xface);
|
||||||
|
if(traceupnp)
|
||||||
|
log.info("Traceupnp: Adding " + name + " to our interface set");
|
||||||
|
else
|
||||||
log.debug("Adding " + name + " to our interface set");
|
log.debug("Adding " + name + " to our interface set");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.info("UPNP Discovery Listener running and ready....");
|
||||||
|
|
||||||
while(true){ //trigger shutdown here
|
while(true){ //trigger shutdown here
|
||||||
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(isSSDPDiscovery(packetString)){
|
|
||||||
log.debug("Got SSDP Discovery packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort());
|
|
||||||
sendUpnpResponse(responseSocket, packet.getAddress(), packet.getPort());
|
sendUpnpResponse(responseSocket, packet.getAddress(), packet.getPort());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("UpnpListener encountered an error. Shutting down", e);
|
log.error("UpnpListener encountered an error opening sockets. Shutting down", e);
|
||||||
|
|
||||||
}
|
}
|
||||||
log.info("UPNP Discovery Listener Stopped");
|
log.info("UPNP Discovery Listener Stopped");
|
||||||
@@ -78,33 +90,54 @@ 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){
|
||||||
if(body != null && body.startsWith("M-SEARCH * HTTP/1.1") && body.contains("MAN: \"ssdp:discover\"")){
|
//Only respond to discover request for strict upnp form
|
||||||
|
String packetString = new String(packet.getData());
|
||||||
|
if(packetString != null && packetString.startsWith("M-SEARCH * HTTP/1.1") && packetString.contains("\"ssdp:discover\"")){
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
log.info("Traceupnp: isSSDPDiscovery found message to be valid under strict rules - strict: " + strict);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (!strict)
|
||||||
|
{
|
||||||
|
if(traceupnp)
|
||||||
|
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);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String discoveryTemplate = "HTTP/1.1 200 OK\r\n" +
|
String discoveryTemplate = "HTTP/1.1 200 OK\r\n" +
|
||||||
"CACHE-CONTROL: max-age=86400\r\n" +
|
"CACHE-CONTROL: max-age=86400\r\n" +
|
||||||
"EXT:\r\n" +
|
"EXT:\r\n" +
|
||||||
"LOCATION: http://%s:%s/upnp/amazon-ha-bridge/setup.xml\r\n" +
|
"LOCATION: http://%s:%s/description.xml\r\n" +
|
||||||
"OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" +
|
"SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/0.1\r\n" +
|
||||||
"01-NLS: %s\r\n" +
|
|
||||||
"ST: urn:schemas-upnp-org:device:basic:1\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";
|
"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 = String.format(discoveryTemplate, responseAddress, httpServerPort, getRandomUUIDString());
|
String discoveryResponse = null;
|
||||||
log.debug("sndUpnpResponse: " + discoveryResponse);
|
discoveryResponse = String.format(discoveryTemplate, responseAddress, httpServerPort);
|
||||||
|
if(traceupnp)
|
||||||
|
log.info("Traceupnp: sendUpnpResponse: " + discoveryResponse);
|
||||||
|
else
|
||||||
|
log.debug("sendUpnpResponse: " + discoveryResponse);
|
||||||
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/
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ public class UpnpSettingsResource {
|
|||||||
|
|
||||||
private Logger log = LoggerFactory.getLogger(UpnpSettingsResource.class);
|
private Logger log = LoggerFactory.getLogger(UpnpSettingsResource.class);
|
||||||
|
|
||||||
private String hueTemplate = "<?xml version=\"1.0\"?>\n" + "<root xmlns=\"urn:schemas-upnp-org:device-1-0\">\n"
|
private BridgeSettings theSettings;
|
||||||
|
|
||||||
|
private String hueTemplate = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + "<root xmlns=\"urn:schemas-upnp-org:device-1-0\">\n"
|
||||||
+ "<specVersion>\n" + "<major>1</major>\n" + "<minor>0</minor>\n" + "</specVersion>\n"
|
+ "<specVersion>\n" + "<major>1</major>\n" + "<minor>0</minor>\n" + "</specVersion>\n"
|
||||||
+ "<URLBase>http://%s:%s/</URLBase>\n" + // hostname string
|
+ "<URLBase>http://%s:%s/</URLBase>\n" + // hostname string
|
||||||
"<device>\n" + "<deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>\n"
|
"<device>\n" + "<deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>\n"
|
||||||
@@ -25,8 +27,8 @@ public class UpnpSettingsResource {
|
|||||||
+ "<manufacturerURL>http://www.bwssystems.com</manufacturerURL>\n"
|
+ "<manufacturerURL>http://www.bwssystems.com</manufacturerURL>\n"
|
||||||
+ "<modelDescription>Hue Emulator for HA bridge</modelDescription>\n"
|
+ "<modelDescription>Hue Emulator for HA bridge</modelDescription>\n"
|
||||||
+ "<modelName>Philips hue bridge 2012</modelName>\n" + "<modelNumber>929000226503</modelNumber>\n"
|
+ "<modelName>Philips hue bridge 2012</modelName>\n" + "<modelNumber>929000226503</modelNumber>\n"
|
||||||
+ "<modelURL>http://www.bwssystems.com/ha-bridge</modelURL>\n"
|
+ "<modelURL>http://www.bwssystems.com/apps.html</modelURL>\n"
|
||||||
+ "<serialNumber>01189998819991197253</serialNumber>\n"
|
+ "<serialNumber>0017880ae670</serialNumber>\n"
|
||||||
+ "<UDN>uuid:88f6698f-2c83-4393-bd03-cd54a9f8595</UDN>\n" + "<serviceList>\n" + "<service>\n"
|
+ "<UDN>uuid:88f6698f-2c83-4393-bd03-cd54a9f8595</UDN>\n" + "<serviceList>\n" + "<service>\n"
|
||||||
+ "<serviceType>(null)</serviceType>\n" + "<serviceId>(null)</serviceId>\n"
|
+ "<serviceType>(null)</serviceType>\n" + "<serviceId>(null)</serviceId>\n"
|
||||||
+ "<controlURL>(null)</controlURL>\n" + "<eventSubURL>(null)</eventSubURL>\n"
|
+ "<controlURL>(null)</controlURL>\n" + "<eventSubURL>(null)</eventSubURL>\n"
|
||||||
@@ -40,26 +42,45 @@ public class UpnpSettingsResource {
|
|||||||
|
|
||||||
public UpnpSettingsResource(BridgeSettings theSettings) {
|
public UpnpSettingsResource(BridgeSettings theSettings) {
|
||||||
super();
|
super();
|
||||||
setupListener(theSettings);
|
this.theSettings = theSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupListener (BridgeSettings theSettings) {
|
public void setupServer() {
|
||||||
// http://ip_address:port/upnp/:id/setup.xml which returns the xml configuration for the location of the hue emulator
|
log.info("Hue description service started....");
|
||||||
get(UPNP_CONTEXT + "/:id/setup.xml", "application/xml", (request, response) -> {
|
// http://ip_adress:port/description.xml which returns the xml configuration for the hue emulator
|
||||||
log.info("upnp device settings requested: " + request.params(":id") + " from " + request.ip());
|
get("/description.xml", "application/xml; charset=utf-8", (request, response) -> {
|
||||||
|
if(theSettings.isTraceupnp())
|
||||||
|
log.info("Traceupnp: upnp device settings requested: " + request.params(":id") + " from " + request.ip() + ":" + request.port());
|
||||||
|
else
|
||||||
|
log.debug("upnp device settings requested: " + request.params(":id") + " from " + request.ip() + ":" + request.port());
|
||||||
String portNumber = Integer.toString(request.port());
|
String portNumber = Integer.toString(request.port());
|
||||||
String filledTemplate = String.format(hueTemplate, theSettings.getUpnpConfigAddress(), portNumber, theSettings.getUpnpConfigAddress());
|
String filledTemplate = null;
|
||||||
|
filledTemplate = String.format(hueTemplate, theSettings.getUpnpConfigAddress(), portNumber, theSettings.getUpnpConfigAddress());
|
||||||
|
if(theSettings.isTraceupnp())
|
||||||
|
log.info("Traceupnp: upnp device settings response: " + filledTemplate);
|
||||||
|
else
|
||||||
log.debug("upnp device settings response: " + filledTemplate);
|
log.debug("upnp device settings response: " + filledTemplate);
|
||||||
response.status(201);
|
// response.header("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
|
||||||
|
// response.header("Pragma", "no-cache");
|
||||||
|
// response.header("Expires", "Mon, 1 Aug 2011 09:00:00 GMT");
|
||||||
|
// response.header("Connection", "close"); // Not sure if the server will actually close the connections by just setting the header
|
||||||
|
// response.header("Access-Control-Max-Age", "0");
|
||||||
|
// response.header("Access-Control-Allow-Origin", "*");
|
||||||
|
// response.header("Access-Control-Allow-Credentials", "true");
|
||||||
|
// response.header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");
|
||||||
|
// response.header("Access-Control-Allow-Headers", "Content-Type");
|
||||||
|
// response.header("Content-Type", "application/xml; charset=utf-8");
|
||||||
|
response.type("application/xml; charset=utf-8");
|
||||||
|
response.status(200);
|
||||||
|
|
||||||
return filledTemplate;
|
return filledTemplate;
|
||||||
} );
|
} );
|
||||||
|
|
||||||
// http://ip_address:port/upnp/settings which returns the bridge configuration settings
|
// http://ip_address:port/upnp/settings which returns the bridge configuration settings
|
||||||
get(UPNP_CONTEXT + "/settings", "application/xml", (request, response) -> {
|
get(UPNP_CONTEXT + "/settings", "application/json", (request, response) -> {
|
||||||
log.debug("bridge settings requested from " + request.ip());
|
log.debug("bridge settings requested from " + request.ip());
|
||||||
|
|
||||||
response.status(201);
|
response.status(200);
|
||||||
|
|
||||||
return theSettings;
|
return theSettings;
|
||||||
}, new JsonTransformer());
|
}, new JsonTransformer());
|
||||||
|
|||||||
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)";
|
||||||
|
else 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,14 +26,19 @@ public class VeraInfo {
|
|||||||
private HttpClient httpClient;
|
private HttpClient httpClient;
|
||||||
private static final String SDATA_REQUEST = ":3480/data_request?id=sdata&output_format=json";
|
private static final String SDATA_REQUEST = ":3480/data_request?id=sdata&output_format=json";
|
||||||
private String veraAddressString;
|
private String veraAddressString;
|
||||||
|
private Boolean validVera;
|
||||||
|
|
||||||
public VeraInfo(String addressString) {
|
public VeraInfo(String addressString, Boolean isValidVera) {
|
||||||
super();
|
super();
|
||||||
httpClient = HttpClients.createMinimal();
|
httpClient = HttpClients.createMinimal();
|
||||||
veraAddressString = addressString;
|
veraAddressString = addressString;
|
||||||
|
validVera = isValidVera;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sdata getSdata() {
|
public Sdata getSdata() {
|
||||||
|
if(!validVera)
|
||||||
|
return new Sdata();
|
||||||
|
|
||||||
String theUrl = "http://" + veraAddressString + SDATA_REQUEST;
|
String theUrl = "http://" + veraAddressString + SDATA_REQUEST;
|
||||||
String theData;
|
String theData;
|
||||||
|
|
||||||
@@ -57,27 +62,37 @@ public class VeraInfo {
|
|||||||
Device theDevice = null;
|
Device theDevice = null;
|
||||||
while (theIterator.hasNext()) {
|
while (theIterator.hasNext()) {
|
||||||
theDevice = theIterator.next();
|
theDevice = theIterator.next();
|
||||||
|
if(theDevice.getRoom() != null && roomMap.get(theDevice.getRoom()) != null)
|
||||||
theDevice.setRoom(roomMap.get(theDevice.getRoom()).getName());
|
theDevice.setRoom(roomMap.get(theDevice.getRoom()).getName());
|
||||||
|
else
|
||||||
|
theDevice.setRoom("no room");
|
||||||
|
|
||||||
|
if(theDevice.getCategory() != null && categoryMap.get(theDevice.getCategory()) != null)
|
||||||
theDevice.setCategory(categoryMap.get(theDevice.getCategory()).getName());
|
theDevice.setCategory(categoryMap.get(theDevice.getCategory()).getName());
|
||||||
|
else
|
||||||
|
theDevice.setCategory("<unknown>");
|
||||||
}
|
}
|
||||||
|
|
||||||
ListIterator<Scene> theSecneIter = theSdata.getScenes().listIterator();
|
ListIterator<Scene> theSecneIter = theSdata.getScenes().listIterator();
|
||||||
Scene theScene = null;
|
Scene theScene = null;
|
||||||
while (theSecneIter.hasNext()) {
|
while (theSecneIter.hasNext()) {
|
||||||
theScene = theSecneIter.next();
|
theScene = theSecneIter.next();
|
||||||
|
if(theScene.getRoom() != null && roomMap.get(theScene.getRoom()) != null)
|
||||||
theScene.setRoom(roomMap.get(theScene.getRoom()).getName());
|
theScene.setRoom(roomMap.get(theScene.getRoom()).getName());
|
||||||
|
else
|
||||||
|
theScene.setRoom("no room");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function executes the url against the vera
|
// This function executes the url against the vera
|
||||||
protected String doHttpGETRequest(String url) {
|
protected String doHttpGETRequest(String url) {
|
||||||
log.info("calling GET on URL: " + url);
|
log.debug("calling GET on URL: " + url);
|
||||||
HttpGet httpGet = new HttpGet(url);
|
HttpGet httpGet = new HttpGet(url);
|
||||||
try {
|
try {
|
||||||
HttpResponse response = httpClient.execute(httpGet);
|
HttpResponse response = httpClient.execute(httpGet);
|
||||||
String theContent = EntityUtils.toString(response.getEntity()); //read content for data
|
String theContent = EntityUtils.toString(response.getEntity()); //read content for data
|
||||||
EntityUtils.consume(response.getEntity()); //close out inputstream ignore content
|
EntityUtils.consume(response.getEntity()); //close out inputstream ignore content
|
||||||
log.info("GET on URL responded: " + response.getStatusLine().getStatusCode());
|
log.debug("GET on URL responded: " + response.getStatusLine().getStatusCode());
|
||||||
if(response.getStatusLine().getStatusCode() == 200){
|
if(response.getStatusLine().getStatusCode() == 200){
|
||||||
return theContent;
|
return theContent;
|
||||||
}
|
}
|
||||||
|
|||||||
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
11
src/main/resources/public/css/main.css
Normal file
11
src/main/resources/public/css/main.css
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
body {
|
||||||
|
padding-top: 60px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sortorder:after {
|
||||||
|
content: '\25b2';
|
||||||
|
}
|
||||||
|
.sortorder.reverse:after {
|
||||||
|
content: '\25bc';
|
||||||
|
}
|
||||||
@@ -5,12 +5,7 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>HA Bridge</title>
|
<title>HA Bridge</title>
|
||||||
<style>
|
<link href="css/main.css" rel="stylesheet">
|
||||||
body {
|
|
||||||
padding-top: 60px;
|
|
||||||
padding-bottom: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<link href="css/bootstrap.min.css" rel="stylesheet">
|
<link href="css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
|
||||||
<!--[if lt IE 9]>
|
<!--[if lt IE 9]>
|
||||||
@@ -21,7 +16,7 @@
|
|||||||
<body>
|
<body>
|
||||||
|
|
||||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||||
<div class="container">
|
<div class="container" ng-controller="VersionController">
|
||||||
<div class="navbar-header">
|
<div class="navbar-header">
|
||||||
<button type="button" class="navbar-toggle">
|
<button type="button" class="navbar-toggle">
|
||||||
<span class="sr-only">Toggle navigation</span>
|
<span class="sr-only">Toggle navigation</span>
|
||||||
@@ -35,13 +30,13 @@
|
|||||||
<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 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"
|
||||||
aria-expanded="false">About <span class="caret"></span></a>
|
aria-expanded="false">About <span class="caret"></span></a>
|
||||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
<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.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="http://www.amazon.com/echo" target="_blank">Amazon Echo</a></li>
|
||||||
<li><a href="#">HA Bridge Version 0.3.0</a></li>
|
<li><a href="">HA Bridge Version {{bridge.habridgeversion}}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -18,6 +18,12 @@ app.config(function ($routeProvider) {
|
|||||||
}).when('/verascenes', {
|
}).when('/verascenes', {
|
||||||
templateUrl: 'views/verascene.html',
|
templateUrl: 'views/verascene.html',
|
||||||
controller: 'AddingController'
|
controller: 'AddingController'
|
||||||
|
}).when('/harmonydevices', {
|
||||||
|
templateUrl: 'views/harmonydevice.html',
|
||||||
|
controller: 'AddingController'
|
||||||
|
}).when('/harmonyactivities', {
|
||||||
|
templateUrl: 'views/harmonyactivity.html',
|
||||||
|
controller: 'AddingController'
|
||||||
}).otherwise({
|
}).otherwise({
|
||||||
templateUrl: 'views/configuration.html',
|
templateUrl: 'views/configuration.html',
|
||||||
controller: 'ViewingController'
|
controller: 'ViewingController'
|
||||||
@@ -26,6 +32,9 @@ app.config(function ($routeProvider) {
|
|||||||
|
|
||||||
app.run( function (bridgeService) {
|
app.run( function (bridgeService) {
|
||||||
bridgeService.loadBridgeSettings();
|
bridgeService.loadBridgeSettings();
|
||||||
|
bridgeService.updateShowVera();
|
||||||
|
bridgeService.updateShowHarmony();
|
||||||
|
bridgeService.getHABridgeVersion();
|
||||||
});
|
});
|
||||||
|
|
||||||
app.factory('BridgeSettings', function() {
|
app.factory('BridgeSettings', function() {
|
||||||
@@ -36,6 +45,10 @@ app.factory('BridgeSettings', function() {
|
|||||||
BridgeSettings.upnpdevicedb = "";
|
BridgeSettings.upnpdevicedb = "";
|
||||||
BridgeSettings.upnpresponseport = "";
|
BridgeSettings.upnpresponseport = "";
|
||||||
BridgeSettings.veraaddress = "";
|
BridgeSettings.veraaddress = "";
|
||||||
|
BridgeSettings.harmonyaddress = "";
|
||||||
|
BridgeSettings.upnpstrict = "";
|
||||||
|
BridgeSettings.traceupnp = "";
|
||||||
|
BridgeSettings.devmode = "";
|
||||||
|
|
||||||
BridgeSettings.setupnpconfigaddress = function(aconfigaddress){
|
BridgeSettings.setupnpconfigaddress = function(aconfigaddress){
|
||||||
BridgeSettings.upnpconfigaddress = aconfigaddress;
|
BridgeSettings.upnpconfigaddress = aconfigaddress;
|
||||||
@@ -56,14 +69,26 @@ app.factory('BridgeSettings', function() {
|
|||||||
BridgeSettings.setveraaddress = function(averaaddress){
|
BridgeSettings.setveraaddress = function(averaaddress){
|
||||||
BridgeSettings.veraaddress = averaaddress;
|
BridgeSettings.veraaddress = averaaddress;
|
||||||
};
|
};
|
||||||
|
BridgeSettings.setharmonyaddress = function(aharmonyaddress){
|
||||||
|
BridgeSettings.harmonyaddress = aharmonyaddress;
|
||||||
|
};
|
||||||
|
BridgeSettings.setupnpstrict = function(aupnpstrict){
|
||||||
|
BridgeSettings.upnpstrict = aupnpstrict;
|
||||||
|
};
|
||||||
|
BridgeSettings.settraceupnp = function(atraceupnp){
|
||||||
|
BridgeSettings.traceupnp = atraceupnp;
|
||||||
|
};
|
||||||
|
BridgeSettings.setdevmode = function(adevmode){
|
||||||
|
BridgeSettings.devmode = adevmode;
|
||||||
|
};
|
||||||
|
|
||||||
return BridgeSettings;
|
return BridgeSettings;
|
||||||
});
|
});
|
||||||
|
|
||||||
app.service('bridgeService', function ($http, BridgeSettings) {
|
app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||||
var self = this;
|
var self = this;
|
||||||
self.BridgeSettings = BridgeSettings;
|
self.BridgeSettings = BridgeSettings;
|
||||||
this.state = {base: window.location.origin + "/api/devices", upnpbase: window.location.origin + "/upnp/settings", devices: [], device: [], error: ""};
|
this.state = {base: window.location.origin + "/api/devices", upnpbase: window.location.origin + "/upnp/settings", huebase: window.location.origin + "/api", devices: [], device: [], error: "", showVera: false, showHarmony: false, habridgeversion: ""};
|
||||||
|
|
||||||
this.viewDevices = function () {
|
this.viewDevices = function () {
|
||||||
this.state.error = "";
|
this.state.error = "";
|
||||||
@@ -75,8 +100,24 @@ app.service('bridgeService', function ($http, BridgeSettings) {
|
|||||||
if (error.data) {
|
if (error.data) {
|
||||||
self.state.error = error.data.message;
|
self.state.error = error.data.message;
|
||||||
} else {
|
} else {
|
||||||
self.state.error = "If you're not seeing any devices, you may be running into problems with CORS. " +
|
self.state.error = "Some error occurred.";
|
||||||
"You can work around this by running a fresh launch of Chrome with the --disable-web-security flag.";
|
}
|
||||||
|
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);
|
console.log(error);
|
||||||
}
|
}
|
||||||
@@ -92,20 +133,50 @@ app.service('bridgeService', function ($http, BridgeSettings) {
|
|||||||
self.BridgeSettings.setupnpdevicedb(response.data.upnpdevicedb);
|
self.BridgeSettings.setupnpdevicedb(response.data.upnpdevicedb);
|
||||||
self.BridgeSettings.setupnpresponseport(response.data.upnpresponseport);
|
self.BridgeSettings.setupnpresponseport(response.data.upnpresponseport);
|
||||||
self.BridgeSettings.setveraaddress(response.data.veraaddress);
|
self.BridgeSettings.setveraaddress(response.data.veraaddress);
|
||||||
|
self.BridgeSettings.setharmonyaddress(response.data.harmonyaddress);
|
||||||
|
self.BridgeSettings.settraceupnp(response.data.traceupnp);
|
||||||
|
self.BridgeSettings.setupnpstrict(response.data.upnpstrict);
|
||||||
|
self.BridgeSettings.setdevmode(response.data.devmode);
|
||||||
|
if(self.BridgeSettings.veraaddress == "1.1.1.1" || self.BridgeSettings.veraaddress == "")
|
||||||
|
self.state.showVera = false;
|
||||||
|
else
|
||||||
|
self.state.showVera = true;
|
||||||
|
if(self.BridgeSettings.harmonyaddress == "1.1.1.1" || self.BridgeSettings.harmonyaddress == "")
|
||||||
|
self.state.showHarmony = false;
|
||||||
|
else
|
||||||
|
self.state.showHarmony = true;
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
if (error.data) {
|
if (error.data) {
|
||||||
self.state.error = error.data.message;
|
$window.alert("Load Bridge Settings Error: " + error.data.message);
|
||||||
} else {
|
} else {
|
||||||
self.state.error = "If you're not seeing any settings, you may be running into problems with CORS. " +
|
$window.alert("Load Bridge Settings Error: unknown");
|
||||||
"You can work around this by running a fresh launch of Chrome with the --disable-web-security flag.";
|
|
||||||
}
|
}
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.updateShowVera = function () {
|
||||||
|
if(self.BridgeSettings.veraaddress == "1.1.1.1" || self.BridgeSettings.veraaddress == "")
|
||||||
|
this.state.showVera = false;
|
||||||
|
else
|
||||||
|
this.state.showVera = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateShowHarmony = function () {
|
||||||
|
if(self.BridgeSettings.harmonyaddress == "1.1.1.1" || self.BridgeSettings.harmonyaddress == "")
|
||||||
|
this.state.showHarmony = false;
|
||||||
|
else
|
||||||
|
this.state.showHarmony = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.viewVeraDevices = function () {
|
this.viewVeraDevices = function () {
|
||||||
|
this.state.error = "";
|
||||||
|
if(!this.state.showVera)
|
||||||
|
return;
|
||||||
this.state.error = "";
|
this.state.error = "";
|
||||||
return $http.get(this.state.base + "/vera/devices").then(
|
return $http.get(this.state.base + "/vera/devices").then(
|
||||||
function (response) {
|
function (response) {
|
||||||
@@ -113,70 +184,130 @@ app.service('bridgeService', function ($http, BridgeSettings) {
|
|||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
if (error.data) {
|
if (error.data) {
|
||||||
self.state.error = error.data.message;
|
$window.alert("Get Vera Devices Error: " + error.data.message);
|
||||||
} else {
|
} else {
|
||||||
self.state.error = "If you're not seeing any address, you may be running into problems with CORS. " +
|
$window.alert("Get Vera Devices Error: unknown");
|
||||||
"You can work around this by running a fresh launch of Chrome with the --disable-web-security flag.";
|
|
||||||
}
|
}
|
||||||
console.log(error);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.viewVeraScenes = function () {
|
this.viewVeraScenes = function () {
|
||||||
this.state.error = "";
|
this.state.error = "";
|
||||||
|
if(!this.state.showVera)
|
||||||
|
return;
|
||||||
return $http.get(this.state.base + "/vera/scenes").then(
|
return $http.get(this.state.base + "/vera/scenes").then(
|
||||||
function (response) {
|
function (response) {
|
||||||
self.state.verascenes = response.data;
|
self.state.verascenes = response.data;
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
if (error.data) {
|
if (error.data) {
|
||||||
self.state.error = error.data.message;
|
$window.alert("Get Vera Scenes Error: " + error.data.message);
|
||||||
} else {
|
} else {
|
||||||
self.state.error = "If you're not seeing any address, you may be running into problems with CORS. " +
|
$window.alert("Get Vera Scenes Error: unknown");
|
||||||
"You can work around this by running a fresh launch of Chrome with the --disable-web-security flag.";
|
|
||||||
}
|
}
|
||||||
console.log(error);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.addDevice = function (id, name, type, onUrl, offUrl) {
|
this.viewHarmonyActivities = function () {
|
||||||
this.state.error = "";
|
this.state.error = "";
|
||||||
if (id) {
|
if(!this.state.showHarmony)
|
||||||
var putUrl = this.state.base + "/" + id;
|
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.findDeviceByMapId = function(id) {
|
||||||
|
for(var i = 0; i < this.state.devices.length; i++) {
|
||||||
|
if(this.state.devices[i].mapId == id)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.addDevice = function (device) {
|
||||||
|
this.state.error = "";
|
||||||
|
if(device.httpVerb != null && device.httpVerb != "")
|
||||||
|
device.deviceType = "custom";
|
||||||
|
if (device.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: "switch",
|
mapId: device.mapId,
|
||||||
onUrl: onUrl,
|
mapType: device.mapType,
|
||||||
offUrl: offUrl
|
deviceType: device.deviceType,
|
||||||
|
onUrl: device.onUrl,
|
||||||
|
offUrl: device.offUrl,
|
||||||
|
httpVerb: device.httpVerb,
|
||||||
|
contentType: device.contentType,
|
||||||
|
contentBody: device.contentBody,
|
||||||
|
contentBodyOff: device.contentBodyOff
|
||||||
}).then(
|
}).then(
|
||||||
function (response) {
|
function (response) {
|
||||||
self.viewDevices();
|
self.viewDevices();
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
if (error.data) {
|
if (error.data) {
|
||||||
self.state.error = error.data.message;
|
$window.alert("Edit Device Error: " + error.data.message);
|
||||||
}
|
}
|
||||||
console.log(error);
|
$window.alert("Edit Device Error: unknown");
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
if(device.deviceType == null || device.deviceType == "")
|
||||||
|
device.deviceType = "switch";
|
||||||
|
if(device.httpVerb != null && device.httpVerb != "")
|
||||||
|
device.deviceType = "custom";
|
||||||
return $http.post(this.state.base, {
|
return $http.post(this.state.base, {
|
||||||
name: name,
|
name: device.name,
|
||||||
deviceType: "switch",
|
mapId: device.mapId,
|
||||||
onUrl: onUrl,
|
mapType: device.mapType,
|
||||||
offUrl: offUrl
|
deviceType: device.deviceType,
|
||||||
|
onUrl: device.onUrl,
|
||||||
|
offUrl: device.offUrl,
|
||||||
|
httpVerb: device.httpVerb,
|
||||||
|
contentType: device.contentType,
|
||||||
|
contentBody: device.contentBody,
|
||||||
|
contentBodyOff: device.contentBodyOff
|
||||||
}).then(
|
}).then(
|
||||||
function (response) {
|
function (response) {
|
||||||
self.viewDevices();
|
self.viewDevices();
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
if (error.data) {
|
if (error.data) {
|
||||||
self.state.error = error.data.message;
|
$window.alert("Add new Device Error: " + error.data.message);
|
||||||
}
|
}
|
||||||
console.log(error);
|
$window.alert("Add new Device Error: unknown");
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -192,52 +323,130 @@ app.service('bridgeService', function ($http, BridgeSettings) {
|
|||||||
if (error.data) {
|
if (error.data) {
|
||||||
self.state.error = error.data.message;
|
self.state.error = error.data.message;
|
||||||
}
|
}
|
||||||
console.log(error);
|
$window.alert("Delete Device Error: unknown");
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.editDevice = function (id, name, onUrl, offUrl) {
|
this.deleteDeviceByMapId = function (id) {
|
||||||
self.state.device = {id: id, name: name, onUrl: onUrl, offUrl: offUrl};
|
for(var i = 0; i < this.state.devices.length; i++) {
|
||||||
|
if(this.state.devices[i].mapId == id)
|
||||||
|
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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
app.controller('ViewingController', function ($scope, $location, bridgeService, BridgeSettings) {
|
app.controller('ViewingController', function ($scope, $location, $http, $window, bridgeService, BridgeSettings) {
|
||||||
|
|
||||||
$scope.BridgeSettings = bridgeService.BridgeSettings;
|
$scope.BridgeSettings = bridgeService.BridgeSettings;
|
||||||
bridgeService.viewDevices();
|
bridgeService.viewDevices();
|
||||||
$scope.bridge = bridgeService.state;
|
$scope.bridge = bridgeService.state;
|
||||||
|
bridgeService.updateShowVera();
|
||||||
|
bridgeService.updateShowHarmony();
|
||||||
|
$scope.visible = false;
|
||||||
|
$scope.imgUrl = "glyphicon glyphicon-plus";
|
||||||
|
$scope.predicate = '';
|
||||||
|
$scope.reverse = true;
|
||||||
|
$scope.order = function(predicate) {
|
||||||
|
$scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
|
||||||
|
$scope.predicate = predicate;
|
||||||
|
};
|
||||||
$scope.deleteDevice = function (device) {
|
$scope.deleteDevice = function (device) {
|
||||||
bridgeService.deleteDevice(device.id);
|
bridgeService.deleteDevice(device.id);
|
||||||
};
|
};
|
||||||
$scope.testUrl = function (url) {
|
$scope.testUrl = function (device, type) {
|
||||||
window.open(url, "_blank");
|
bridgeService.testUrl(device, type);
|
||||||
};
|
};
|
||||||
$scope.setBridgeUrl = function (url) {
|
$scope.setBridgeUrl = function (url) {
|
||||||
bridgeService.state.base = url;
|
bridgeService.state.base = url;
|
||||||
bridgeService.viewDevices();
|
bridgeService.viewDevices();
|
||||||
};
|
};
|
||||||
$scope.editDevice = function (device) {
|
$scope.editDevice = function (device) {
|
||||||
bridgeService.editDevice(device.id, device.name, device.onUrl, device.offUrl);
|
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, bridgeService, BridgeSettings) {
|
app.controller('AddingController', function ($scope, $location, $http, bridgeService, BridgeSettings) {
|
||||||
|
|
||||||
$scope.device = {id: "", name: "", type: "switch", onUrl: "", offUrl: ""};
|
$scope.device = {id: "", name: "", deviceType: "switch", onUrl: "", offUrl: ""};
|
||||||
$scope.vera = {base: "", port: "3480", id: ""};
|
$scope.vera = {base: "", port: "3480", id: ""};
|
||||||
$scope.vera.base = "http://" + BridgeSettings.veraaddress;
|
$scope.vera.base = "http://" + BridgeSettings.veraaddress;
|
||||||
bridgeService.device = $scope.device;
|
bridgeService.device = $scope.device;
|
||||||
bridgeService.viewVeraDevices();
|
bridgeService.viewVeraDevices();
|
||||||
bridgeService.viewVeraScenes();
|
bridgeService.viewVeraScenes();
|
||||||
|
bridgeService.viewHarmonyActivities();
|
||||||
|
bridgeService.viewHarmonyDevices();
|
||||||
$scope.bridge = bridgeService.state;
|
$scope.bridge = bridgeService.state;
|
||||||
|
bridgeService.updateShowVera();
|
||||||
|
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.reverse = true;
|
||||||
|
$scope.device_dim_control = "";
|
||||||
|
$scope.order = function(predicate) {
|
||||||
|
$scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
|
||||||
|
$scope.predicate = predicate;
|
||||||
|
};
|
||||||
|
|
||||||
$scope.buildUrlsUsingDevice = function () {
|
$scope.buildUrlsUsingDevice = function (dim_control) {
|
||||||
if ($scope.vera.base.indexOf("http") < 0) {
|
if ($scope.vera.base.indexOf("http") < 0) {
|
||||||
$scope.vera.base = "http://" + $scope.vera.base;
|
$scope.vera.base = "http://" + $scope.vera.base;
|
||||||
}
|
}
|
||||||
|
$scope.device.deviceType = "switch";
|
||||||
|
$scope.device.mapType = "veraDevice";
|
||||||
|
$scope.device.mapId = $scope.vera.id;
|
||||||
|
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
|
||||||
|
+ "/data_request?id=action&output_format=json&DeviceNum="
|
||||||
|
+ $scope.vera.id
|
||||||
|
+ "&serviceId=urn:upnp-org:serviceId:Dimming1&action=SetLoadLevelTarget&newLoadlevelTarget="
|
||||||
|
+ dim_control;
|
||||||
|
else
|
||||||
$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:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1&DeviceNum="
|
+ "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1&DeviceNum="
|
||||||
+ $scope.vera.id;
|
+ $scope.vera.id;
|
||||||
@@ -250,6 +459,9 @@ app.controller('AddingController', function ($scope, bridgeService, BridgeSettin
|
|||||||
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 = "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;
|
||||||
@@ -258,11 +470,21 @@ app.controller('AddingController', function ($scope, bridgeService, BridgeSettin
|
|||||||
+ $scope.vera.id;
|
+ $scope.vera.id;
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.buildDeviceUrls = function (veradevice) {
|
$scope.buildDeviceUrls = function (veradevice, dim_control) {
|
||||||
if ($scope.vera.base.indexOf("http") < 0) {
|
if ($scope.vera.base.indexOf("http") < 0) {
|
||||||
$scope.vera.base = "http://" + $scope.vera.base;
|
$scope.vera.base = "http://" + $scope.vera.base;
|
||||||
}
|
}
|
||||||
|
$scope.device.deviceType = "switch";
|
||||||
$scope.device.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)
|
||||||
|
$scope.device.onUrl = $scope.vera.base + ":" + $scope.vera.port
|
||||||
|
+ "/data_request?id=action&output_format=json&DeviceNum="
|
||||||
|
+ veradevice.id
|
||||||
|
+ "&serviceId=urn:upnp-org:serviceId:Dimming1&action=SetLoadLevelTarget&newLoadlevelTarget="
|
||||||
|
+ dim_control;
|
||||||
|
else
|
||||||
$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:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1&DeviceNum="
|
+ "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1&DeviceNum="
|
||||||
+ veradevice.id;
|
+ veradevice.id;
|
||||||
@@ -275,7 +497,10 @@ app.controller('AddingController', function ($scope, bridgeService, BridgeSettin
|
|||||||
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 = "scene";
|
||||||
$scope.device.name = verascene.name;
|
$scope.device.name = verascene.name;
|
||||||
|
$scope.devoce.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;
|
||||||
@@ -284,26 +509,134 @@ app.controller('AddingController', function ($scope, bridgeService, BridgeSettin
|
|||||||
+ verascene.id;
|
+ verascene.id;
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.testUrl = function (url) {
|
$scope.buildActivityUrls = function (harmonyactivity) {
|
||||||
window.open(url, "_blank");
|
$scope.device.deviceType = "activity";
|
||||||
|
$scope.device.name = harmonyactivity.label;
|
||||||
|
$scope.device.mapType = "harmonyActivity";
|
||||||
|
$scope.device.mapId = harmonyactivity.id;
|
||||||
|
$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.mapType = "harmonyButton";
|
||||||
|
$scope.device.mapId = harmonydevice.id + "-" + onbutton + "-" + offbutton;
|
||||||
|
$scope.device.onUrl = "{\"device\":\"" + harmonydevice.id + "\",\"button\":\"" + onbutton + "\"}";
|
||||||
|
$scope.device.offUrl = "{\"device\":\"" + harmonydevice.id + "\",\"button\":\"" + offbutton + "\"}";
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.testUrl = function (device, type) {
|
||||||
|
bridgeService.testUrl(device, type);
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.addDevice = function () {
|
$scope.addDevice = function () {
|
||||||
bridgeService.addDevice($scope.device.id, $scope.device.name, $scope.device.deviceType, $scope.device.onUrl, $scope.device.offUrl).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.offUrl = "";
|
$scope.device.offUrl = "";
|
||||||
|
$scope.device.httpVerb = null;
|
||||||
|
$scope.device.contentType = null;
|
||||||
|
$scope.device.contentBody = null;
|
||||||
|
$scope.device.contentBodyOff = null;
|
||||||
|
$location.path('/#');
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$scope.toggleActivities = function () {
|
||||||
|
$scope.activitiesVisible = !$scope.activitiesVisible;
|
||||||
|
if($scope.activitiesVisible)
|
||||||
|
$scope.imgActivitiesUrl = "glyphicon glyphicon-minus";
|
||||||
|
else
|
||||||
|
$scope.imgActivitiesUrl = "glyphicon glyphicon-plus";
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.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) {
|
||||||
|
bridgeService.deleteDeviceByMapId(id);
|
||||||
|
};
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.filter('availableId', 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)){
|
||||||
|
out.push(input[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.filter('unavailableId', 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)){
|
||||||
|
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;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.controller('VersionController', function ($scope, bridgeService) {
|
||||||
|
$scope.bridge = bridgeService.state;
|
||||||
|
});
|
||||||
@@ -1,17 +1,68 @@
|
|||||||
|
<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>
|
||||||
|
|
||||||
<h2>Configuration <a class="btn btn-primary pull-right" href="#/editor"><i
|
|
||||||
class="icon-plis-sign icon-white"></i> Manual Add</a>
|
<div ng-controller="ErrorsController">
|
||||||
<a class="btn btn-primary pull-right" href="#/verascenes"><i
|
<div ng-if="bridge.error"
|
||||||
class="icon-plis-sign icon-white"></i> Vera Scenes</a>
|
class="alert alert-warning alert-dismissible" role="alert">
|
||||||
<a class="btn btn-primary pull-right" href="#/veradevices"><i
|
<button type="button" class="close" data-dismiss="alert"
|
||||||
class="icon-plis-sign icon-white"></i> Vera Devices</a>
|
aria-label="Close">
|
||||||
</h2>
|
<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 panel-default bridgeServer">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h1 class="panel-title">Bridge settings</h1>
|
<h1 class="panel-title">Bridge settings <a ng-click="toggle()"><span class={{imgUrl}} aria-hidden="true"></a></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">
|
||||||
@@ -55,51 +106,22 @@
|
|||||||
<td>vera.address</td>
|
<td>vera.address</td>
|
||||||
<td>{{BridgeSettings.veraaddress}}</td>
|
<td>{{BridgeSettings.veraaddress}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<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>
|
<tr>
|
||||||
<th>ID</th>
|
<td>harmony.address</td>
|
||||||
<th>Name</th>
|
<td>{{BridgeSettings.harmonyaddress}}</td>
|
||||||
<th>Type</th>
|
|
||||||
<th>Actions</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
<tr>
|
||||||
<tr ng-repeat="device in bridge.devices">
|
<td>upnp.strict</td>
|
||||||
<td>{{device.id}}</td>
|
<td>{{BridgeSettings.upnpstrict}}</td>
|
||||||
<td>{{device.name}}</td>
|
</tr>
|
||||||
<td>{{device.deviceType}}</td>
|
<tr>
|
||||||
<td>
|
<td>trace.upnp</td>
|
||||||
<button class="btn btn-info" type="submit"
|
<td>{{BridgeSettings.traceupnp}}</td>
|
||||||
ng-click="testUrl(device.onUrl)">Test ON</button>
|
</tr>
|
||||||
<button class="btn btn-info" type="submit"
|
<tr>
|
||||||
ng-click="testUrl(device.offUrl)">Test OFF</button>
|
<td>dev.mode</td>
|
||||||
<button class="btn btn-warning" type="submit"
|
<td>{{BridgeSettings.devmode}}</td>
|
||||||
ng-click="editDevice(device)">Edit</button>
|
|
||||||
<button class="btn btn-danger" type="submit"
|
|
||||||
ng-click="deleteDevice(device)">Delete</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
<h2>
|
<ul class="nav nav-pills" role="tablist">
|
||||||
Device Editor <a class="btn btn-primary pull-right" href="/">
|
<li role="presentation"><a href="#">Configuration</a></li>
|
||||||
Configuration</a>
|
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
|
||||||
</h2>
|
<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>
|
||||||
|
|
||||||
<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">
|
||||||
@@ -22,26 +27,115 @@
|
|||||||
Update Device</button>
|
Update Device</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<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="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
|
||||||
URL </label>
|
URL </label>
|
||||||
|
|
||||||
<div class="col-xs-8 col-sm-7">
|
<div class="col-xs-8 col-sm-7">
|
||||||
<input type="text" 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">
|
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
|
|
||||||
ng-click="testUrl(device.onUrl)">Test</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
<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-off-url">Off URL </label>
|
for="device-off-url">Off URL </label>
|
||||||
|
|
||||||
<div class="col-xs-8 col-sm-7">
|
<div class="col-xs-8 col-sm-7">
|
||||||
<input type="text" 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">
|
ng-model="device.offUrl" placeholder="URL to turn device off"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="row">
|
||||||
|
<label class="col-xs-12 col-sm-2 control-label" for="device-http-verb">Http Verb
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="col-xs-8 col-sm-7">
|
||||||
|
<select name="device-http-verb" id="device-http-verb" ng-model="device.httpVerb">
|
||||||
|
<option value="">---Please select---</option> <!-- not selected / blank option -->
|
||||||
|
<option value="GET">GET</option>
|
||||||
|
<option value="PUT">PUT</option>
|
||||||
|
<option value="POST">POST</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ng-if="device.httpVerb" class="form-group">
|
||||||
|
<div class="row">
|
||||||
|
<label class="col-xs-12 col-sm-2 control-label" for="device-content-type">Content Type
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="col-xs-8 col-sm-7">
|
||||||
|
<select name="device-content-type" id="device-content-type" ng-model="device.contentType">
|
||||||
|
<option value="">---Please select---</option> <!-- not selected / blank option -->
|
||||||
|
<option value="application/atom+xml">application/atom+xml</option>
|
||||||
|
<option value="application/x-www-form-urlencoded">application/x-www-form-urlencoded</option>
|
||||||
|
<option value="application/json">application/json</option>
|
||||||
|
<option value="application/octet-stream">application/octet-stream</option>
|
||||||
|
<option value="application/svg+xml">application/svg+xml</option>
|
||||||
|
<option value="application/xhtml+xml">application/xhtml+xml</option>
|
||||||
|
<option value="application/xml">application/xml</option>
|
||||||
|
<option value="*">*</option>
|
||||||
|
<option value="multipart/form-data">multipart/form-data</option>
|
||||||
|
<option value="text/html">text/html</option>
|
||||||
|
<option value="text/plain">text/plain</option>
|
||||||
|
<option value="text/xml">text/xml</option>
|
||||||
|
<option value="*/*">*/*</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ng-if="device.httpVerb" class="form-group">
|
||||||
|
<div class="row">
|
||||||
|
<label class="col-xs-12 col-sm-2 control-label"
|
||||||
|
for="device-content-body">Content Body On</label>
|
||||||
|
|
||||||
|
<div class="col-xs-8 col-sm-7">
|
||||||
|
<textarea rows="3" class="form-control" id="device-content-body"
|
||||||
|
ng-model="device.contentBody" placeholder="Content Body On for specific GET/PUT/POST type"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="clearfix visible-xs"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ng-if="device.httpVerb" class="form-group">
|
||||||
|
<div class="row">
|
||||||
|
<label class="col-xs-12 col-sm-2 control-label"
|
||||||
|
for="device-content-body-off">Content Body Off</label>
|
||||||
|
|
||||||
|
<div class="col-xs-8 col-sm-7">
|
||||||
|
<textarea rows="3" class="form-control" id="device-content-body-off"
|
||||||
|
ng-model="device.contentBodyOff" placeholder="Content Body Off for specific GET/PUT/POST type"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="clearfix visible-xs"></div>
|
||||||
</div>
|
</div>
|
||||||
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
|
|
||||||
ng-click="testUrl(device.offUrl)">Test</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
<h2>
|
<ul class="nav nav-pills" role="tablist">
|
||||||
Manual Add <a class="btn btn-primary pull-right" href="/">
|
<li role="presentation"><a href="#">Configuration</a></li>
|
||||||
Configuration</a>
|
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
|
||||||
</h2>
|
<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">
|
<div class="panel-heading">
|
||||||
<h2 class="panel-title">Generate a new device/scene/control point</h2>
|
<h2 class="panel-title">Generate a new device/scene/control point</h2>
|
||||||
</div>
|
</div>
|
||||||
@@ -40,11 +44,25 @@
|
|||||||
<input type="text" class="form-control" id="vera-id"
|
<input type="text" class="form-control" id="vera-id"
|
||||||
ng-model="vera.id" placeholder="ID">
|
ng-model="vera.id" placeholder="ID">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" ng-click="buildUrlsUsingDevice()"
|
</div>
|
||||||
class="col-xs-4 col-sm-2 btn btn-success">Generate Device
|
<div class="form-group">
|
||||||
|
<label class="col-xs-2 col-sm-2 control-label" for="device-dim-control">Device Dim Control</label>
|
||||||
|
|
||||||
|
<div class="col-xs-10 col-sm-2">
|
||||||
|
<select name="device-dim-control" id="device-dim-control" ng-model="device_dim_control">
|
||||||
|
<option value="">none</option>
|
||||||
|
<option value="${intensity..byte}">Pass-thru Value</option>
|
||||||
|
<option value="${intensity.percent}">Percentage</option>
|
||||||
|
<option value="${intensity.math(X*1)}">Custom Math</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="submit" ng-click="buildUrlsUsingDevice(device_dim_control)"
|
||||||
|
class="col-xs-2 col-sm-2 col-xs-offset-2 col-sm-offset-2 btn btn-success">Generate Device
|
||||||
URLs</button>
|
URLs</button>
|
||||||
<button type="submit" ng-click="buildUrlsUsingScene()"
|
<button type="submit" ng-click="buildUrlsUsingScene()"
|
||||||
class="col-xs-4 col-sm-2 btn btn-success">Generate Scene
|
class="col-xs-2 col-sm-2 col-xs-offset-2 col-sm-offset-2 btn btn-success">Generate Scene
|
||||||
URLs</button>
|
URLs</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -59,6 +77,7 @@
|
|||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<form class="form-horizontal" ng-submit="addDevice()">
|
<form class="form-horizontal" ng-submit="addDevice()">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
<div class="row">
|
||||||
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
|
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
@@ -69,27 +88,92 @@
|
|||||||
<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">
|
||||||
Add Device</button>
|
Add Device</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
<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
|
||||||
URL </label>
|
URL </label>
|
||||||
|
|
||||||
<div class="col-xs-8 col-sm-7">
|
<div class="col-xs-8 col-sm-7">
|
||||||
<input type="text" 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">
|
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
|
|
||||||
ng-click="testUrl(device.onUrl)">Test</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
<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-off-url">Off URL </label>
|
for="device-off-url">Off URL </label>
|
||||||
|
|
||||||
<div class="col-xs-8 col-sm-7">
|
<div class="col-xs-8 col-sm-7">
|
||||||
<input type="text" 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">
|
ng-model="device.offUrl" placeholder="URL to turn device off"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="row">
|
||||||
|
<label class="col-xs-12 col-sm-2 control-label" for="device-http-verb">Http Verb
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="col-xs-8 col-sm-7">
|
||||||
|
<select name="device-http-verb" id="device-http-verb" ng-model="device.httpVerb">
|
||||||
|
<option value="">---Please select---</option> <!-- not selected / blank option -->
|
||||||
|
<option value="GET">GET</option>
|
||||||
|
<option value="PUT">PUT</option>
|
||||||
|
<option value="POST">POST</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ng-if="device.httpVerb" class="form-group">
|
||||||
|
<div class="row">
|
||||||
|
<label class="col-xs-12 col-sm-2 control-label" for="device-content-type">Content Type
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="col-xs-8 col-sm-7">
|
||||||
|
<select name="device-content-type" id="device-content-type" ng-model="device.contentType">
|
||||||
|
<option value="">---Please select---</option> <!-- not selected / blank option -->
|
||||||
|
<option value="application/atom+xml">application/atom+xml</option>
|
||||||
|
<option value="application/x-www-form-urlencoded">application/x-www-form-urlencoded</option>
|
||||||
|
<option value="application/json">application/json</option>
|
||||||
|
<option value="application/octet-stream">application/octet-stream</option>
|
||||||
|
<option value="application/svg+xml">application/svg+xml</option>
|
||||||
|
<option value="application/xhtml+xml">application/xhtml+xml</option>
|
||||||
|
<option value="application/xml">application/xml</option>
|
||||||
|
<option value="*">*</option>
|
||||||
|
<option value="multipart/form-data">multipart/form-data</option>
|
||||||
|
<option value="text/html">text/html</option>
|
||||||
|
<option value="text/plain">text/plain</option>
|
||||||
|
<option value="text/xml">text/xml</option>
|
||||||
|
<option value="*/*">*/*</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ng-if="device.httpVerb" class="form-group">
|
||||||
|
<div class="row">
|
||||||
|
<label class="col-xs-12 col-sm-2 control-label"
|
||||||
|
for="device-content-body">Content Body On</label>
|
||||||
|
|
||||||
|
<div class="col-xs-8 col-sm-7">
|
||||||
|
<textarea rows="3" class="form-control" id="device-content-body"
|
||||||
|
ng-model="device.contentBody" placeholder="Content Body On for specific GET/PUT/POST type"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="clearfix visible-xs"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ng-if="device.httpVerb" class="form-group">
|
||||||
|
<div class="row">
|
||||||
|
<label class="col-xs-12 col-sm-2 control-label"
|
||||||
|
for="device-content-body-off">Content Body Off</label>
|
||||||
|
|
||||||
|
<div class="col-xs-8 col-sm-7">
|
||||||
|
<textarea rows="3" class="form-control" id="device-content-body-off"
|
||||||
|
ng-model="device.contentBodyOff" placeholder="Content Body Off for specific GET/PUT/POST type"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="clearfix visible-xs"></div>
|
||||||
</div>
|
</div>
|
||||||
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
|
|
||||||
ng-click="testUrl(device.offUrl)">Test</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
117
src/main/resources/public/views/harmonyactivity.html
Normal file
117
src/main/resources/public/views/harmonyactivity.html
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
<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 | availableId | 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 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>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tr ng-repeat="harmonyactivity in bridge.harmonyactivities | unavailableId | orderBy:predicate:reverse">
|
||||||
|
<td>{{harmonyactivity.label}}</td>
|
||||||
|
<td>{{harmonyactivity.id}}</td>
|
||||||
|
<td><button class="btn btn-danger" type="submit"
|
||||||
|
ng-click="deleteDeviceByMapId(harmonyactivity.id)">Delete</button></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h2 class="panel-title">Add a 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>
|
||||||
140
src/main/resources/public/views/harmonydevice.html
Normal file
140
src/main/resources/public/views/harmonydevice.html
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
<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 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('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.mapId}}</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-danger" type="submit"
|
||||||
|
ng-click="deleteDeviceByMapId(device.mapId)">Delete</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h2 class="panel-title">Add a 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>
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
<h2>
|
<ul class="nav nav-pills" role="tablist">
|
||||||
Vera Device <a class="btn btn-primary pull-right" href="/">
|
<li role="presentation"><a href="#">Configuration</a></li>
|
||||||
Configuration</a>
|
<li role="presentation" class="active"><a href="#/veradevices">Vera Devices</a></li>
|
||||||
</h2>
|
<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>
|
||||||
|
|
||||||
<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">
|
||||||
@@ -10,32 +14,91 @@
|
|||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<p class="text-muted">You can select a Vera device and generate
|
<p class="text-muted">You can select a Vera device and generate
|
||||||
the add device box selections automatically.</p>
|
the add device box selections automatically.</p><p>Also, use this select menu for which type of dim
|
||||||
|
control you would like to be generated:
|
||||||
|
<select name="device-dim-control" id="device-dim-control" ng-model="device_dim_control">
|
||||||
|
<option value="">none</option>
|
||||||
|
<option value="${intensity..byte}">Pass-thru Value</option>
|
||||||
|
<option value="${intensity.percent}">Percentage</option>
|
||||||
|
<option value="${intensity.math(X*1)}">Custom Math</option>
|
||||||
|
</select>
|
||||||
|
</p>
|
||||||
<table class="table table-bordered table-striped table-hover">
|
<table class="table table-bordered table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>
|
||||||
<th>Id</th>
|
<a href="" ng-click="order('name')">Name</a>
|
||||||
<th>Category</th>
|
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
||||||
<th>Room</th>
|
</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>
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tr ng-repeat="veradevice in bridge.veradevices">
|
<tr ng-repeat="veradevice in bridge.veradevices | availableId | 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>
|
||||||
<td>{{veradevice.room}}</td>
|
<td>{{veradevice.room}}</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-success" type="submit"
|
<button class="btn btn-success" type="submit"
|
||||||
ng-click="buildDeviceUrls(veradevice)">Generate
|
ng-click="buildDeviceUrls(veradevice, device_dim_control)">Generate
|
||||||
Device URLs</button>
|
Device URLs</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</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 | unavailableId | 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(harmonyactivity.id)">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">
|
||||||
@@ -56,26 +119,24 @@
|
|||||||
Add Device</button>
|
Add Device</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
<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
|
||||||
URL </label>
|
URL </label>
|
||||||
|
|
||||||
<div class="col-xs-8 col-sm-7">
|
<div class="col-xs-8 col-sm-7">
|
||||||
<input type="text" 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">
|
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
|
|
||||||
ng-click="testUrl(device.onUrl)">Test</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
<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-off-url">Off URL </label>
|
for="device-off-url">Off URL </label>
|
||||||
|
|
||||||
<div class="col-xs-8 col-sm-7">
|
<div class="col-xs-8 col-sm-7">
|
||||||
<input type="text" 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">
|
ng-model="device.offUrl" placeholder="URL to turn device off"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
|
|
||||||
ng-click="testUrl(device.offUrl)">Test</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
<h2>
|
<ul class="nav nav-pills" role="tablist">
|
||||||
Vera Scene <a class="btn btn-primary pull-right" href="/">
|
<li role="presentation"><a href="#">Configuration</a></li>
|
||||||
Configuration</a>
|
<li role="presentation"><a href="#/veradevices">Vera Devices</a></li>
|
||||||
</h2>
|
<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>
|
||||||
|
|
||||||
<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">
|
||||||
@@ -10,18 +14,27 @@
|
|||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<p class="text-muted">You can select a Vera scene and generate
|
<p class="text-muted">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">
|
<table class="table table-bordered table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>
|
||||||
<th>Id</th>
|
<a href="" ng-click="order('name')">Name</a>
|
||||||
<th>Room</th>
|
<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>
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tr ng-repeat="verascene in bridge.verascenes">
|
<tr ng-repeat="verascene in bridge.verascenes | availableId | 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>
|
||||||
@@ -34,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 | unavailableId | 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(harmonyactivity.id)">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">
|
||||||
@@ -54,26 +102,24 @@
|
|||||||
Add Scene</button>
|
Add Scene</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
<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
|
||||||
URL </label>
|
URL </label>
|
||||||
|
|
||||||
<div class="col-xs-8 col-sm-7">
|
<div class="col-xs-8 col-sm-7">
|
||||||
<input type="text" 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">
|
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
|
|
||||||
ng-click="testUrl(device.onUrl)">Test</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
<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-off-url">Off URL </label>
|
for="device-off-url">Off URL </label>
|
||||||
|
|
||||||
<div class="col-xs-8 col-sm-7">
|
<div class="col-xs-8 col-sm-7">
|
||||||
<input type="text" 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">
|
ng-model="device.offUrl" placeholder="URL to turn device off"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
|
|
||||||
ng-click="testUrl(device.offUrl)">Test</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
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}
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package com.test;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class TestBean {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
try {
|
|
||||||
InetAddress address = InetAddress.getLocalHost();
|
|
||||||
System.out.println("Using InetAddress");
|
|
||||||
System.out.println("Host Address: "+ address.getHostAddress());
|
|
||||||
System.out.println("Host Name: "+ address.getHostName());
|
|
||||||
System.out.println("Address List: "+ Arrays.toString(InetAddress.getAllByName(address.getHostName())));
|
|
||||||
System.out.println("CanonicalHostName: "+ address.getCanonicalHostName());
|
|
||||||
System.out.println("Address: "+ address.getAddress());
|
|
||||||
System.out.println("LocalHost: "+ address.getLocalHost());
|
|
||||||
System.out.println("LoopbackAddress: "+ address.getLoopbackAddress());
|
|
||||||
|
|
||||||
String os = "os.name";
|
|
||||||
String version = "os.version";
|
|
||||||
String arch = "os.arch";
|
|
||||||
System.out.println("Name of the OS: "+ System.getProperty(os));
|
|
||||||
System.out.println("Version of the OS: "+ System.getProperty(version));
|
|
||||||
System.out.println("Architecture of the OS: "+ System.getProperty(arch));
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package demo;
|
|
||||||
|
|
||||||
import com.bwssystems.HABridge.HABridge;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dummy test holder
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class DemoApplicationTests {
|
|
||||||
|
|
||||||
public void contextLoads() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user