mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-18 16:17:30 +00:00
Compare commits
152 Commits
v4.5.0alph
...
v5.2.2RC2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df67980bd6 | ||
|
|
b6b78c4849 | ||
|
|
b1d1f2ac46 | ||
|
|
750056df06 | ||
|
|
3f13e957ad | ||
|
|
afc254720c | ||
|
|
943e4420e6 | ||
|
|
c9e6cd079f | ||
|
|
faae6aa31f | ||
|
|
c25f08f142 | ||
|
|
d6ad9d288e | ||
|
|
3400c4d43a | ||
|
|
ddcbea001c | ||
|
|
9a35e47c27 | ||
|
|
199fcce549 | ||
|
|
bfeb382d1f | ||
|
|
3a93d9e98f | ||
|
|
3b22e3f711 | ||
|
|
5c1f1f5b96 | ||
|
|
82788f1ecd | ||
|
|
d5920e1454 | ||
|
|
b26a63bb7a | ||
|
|
f17cea3c9d | ||
|
|
7f68285a43 | ||
|
|
cb46a13802 | ||
|
|
de07393e6e | ||
|
|
4b40b03da4 | ||
|
|
4f5d4acf56 | ||
|
|
271bd3913c | ||
|
|
869ffaaf36 | ||
|
|
5a73cc20a9 | ||
|
|
1a936c631c | ||
|
|
1a8a6f7a6f | ||
|
|
879d3b5326 | ||
|
|
3313548ec2 | ||
|
|
e6db6e11e5 | ||
|
|
dc28eb2984 | ||
|
|
b8acb4a52c | ||
|
|
c843e8d1ac | ||
|
|
21fdaf4545 | ||
|
|
db192df2c6 | ||
|
|
4a24d263c1 | ||
|
|
3394559539 | ||
|
|
47074ff60f | ||
|
|
047a7de612 | ||
|
|
7fc7f00308 | ||
|
|
14e940134c | ||
|
|
1897633e75 | ||
|
|
5a052d9374 | ||
|
|
4b048c2a7f | ||
|
|
27f77b9caa | ||
|
|
18c47ee5e4 | ||
|
|
27dd8475e9 | ||
|
|
37b381085c | ||
|
|
b2a30f5771 | ||
|
|
b88b3fa245 | ||
|
|
52aac32474 | ||
|
|
037b151729 | ||
|
|
3f3d643053 | ||
|
|
f27d905869 | ||
|
|
4c694cb285 | ||
|
|
ca2c5f7b04 | ||
|
|
0c49df1473 | ||
|
|
fe613f7688 | ||
|
|
4b247557d4 | ||
|
|
dc49de41ce | ||
|
|
9d07fac929 | ||
|
|
4ecbad6558 | ||
|
|
4c86e42776 | ||
|
|
00dbea6dac | ||
|
|
ed2bf3bd83 | ||
|
|
58fb085180 | ||
|
|
800f5ec2aa | ||
|
|
bdf5770ba0 | ||
|
|
a213672341 | ||
|
|
d337546da7 | ||
|
|
b9437d42e8 | ||
|
|
71c4447d25 | ||
|
|
a489061bac | ||
|
|
75b925992b | ||
|
|
05b9f195d7 | ||
|
|
5eca809c4a | ||
|
|
fa00b7106a | ||
|
|
df85c8a349 | ||
|
|
d8d5e8f39a | ||
|
|
690bdaa748 | ||
|
|
feee22dbac | ||
|
|
548da932ad | ||
|
|
b147f6606e | ||
|
|
31fe05fe2b | ||
|
|
924f3059fb | ||
|
|
5231eac4b0 | ||
|
|
28144312ff | ||
|
|
60e8855aa7 | ||
|
|
5ea14f9069 | ||
|
|
ce79fb4b82 | ||
|
|
98ce4e2a3a | ||
|
|
026626b5ab | ||
|
|
95c342b548 | ||
|
|
cb9312f6c3 | ||
|
|
8831fec6be | ||
|
|
0227a05970 | ||
|
|
087d66694e | ||
|
|
20ad6891e8 | ||
|
|
cd2bd072ed | ||
|
|
3a5262ff33 | ||
|
|
430eff958c | ||
|
|
86371c03b2 | ||
|
|
3207b6b76e | ||
|
|
3d4724ac57 | ||
|
|
63ac729967 | ||
|
|
0900fec60f | ||
|
|
5ccb793ddb | ||
|
|
3ebab82977 | ||
|
|
e877f410f3 | ||
|
|
220e337d08 | ||
|
|
92b7f4e260 | ||
|
|
78d39325b0 | ||
|
|
208b1cad2a | ||
|
|
ff760a488c | ||
|
|
9200c0fc5d | ||
|
|
998450af4e | ||
|
|
d78c7c536d | ||
|
|
a55c53299a | ||
|
|
fb9cc64839 | ||
|
|
409c93bfb2 | ||
|
|
543a79bb66 | ||
|
|
16d1054b96 | ||
|
|
165b6ef9bb | ||
|
|
fb94b858f6 | ||
|
|
ea80925533 | ||
|
|
62b896ee07 | ||
|
|
8657ea6704 | ||
|
|
05bd6b6d77 | ||
|
|
19256e4eaa | ||
|
|
905f6aa9ec | ||
|
|
daa0dac5b9 | ||
|
|
0478fc69f4 | ||
|
|
b99e74823c | ||
|
|
9aaab37a17 | ||
|
|
df618afeda | ||
|
|
d36769e2a0 | ||
|
|
ebeb6be7a7 | ||
|
|
d3979da2b4 | ||
|
|
f276f66991 | ||
|
|
3ac5c10f08 | ||
|
|
13c84ba174 | ||
|
|
b19fe5c86a | ||
|
|
ff9d0a5a77 | ||
|
|
50af884563 | ||
|
|
0737c54a0e | ||
|
|
a7e516925c |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -12,3 +12,10 @@ data
|
||||
/.settings/
|
||||
/start.bat
|
||||
/.classpath
|
||||
|
||||
sftp-config\.json
|
||||
/bin/
|
||||
.vscode/launch.json
|
||||
.vscode/launch.test.json
|
||||
.vscode/settings.json
|
||||
.vscode/tasks.json
|
||||
|
||||
32
pom.xml
32
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>com.bwssystems.HABridge</groupId>
|
||||
<artifactId>ha-bridge</artifactId>
|
||||
<version>4.5.0alpha</version>
|
||||
<version>5.2.2RC2</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HA Bridge</name>
|
||||
@@ -33,7 +33,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.bwssytems</groupId>
|
||||
<artifactId>harmony-java-client</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<version>master-SNAPSHOT</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
@@ -63,7 +63,7 @@
|
||||
<dependency>
|
||||
<groupId>com.sparkjava</groupId>
|
||||
<artifactId>spark-core</artifactId>
|
||||
<version>2.3</version>
|
||||
<version>2.7.2</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
@@ -84,12 +84,12 @@
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.5</version>
|
||||
<version>1.7.24</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.1.5</version>
|
||||
<version>1.2.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
@@ -104,28 +104,34 @@
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
<version>4.0-beta4</version>
|
||||
<version>4.1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.igniterealtime.smack</groupId>
|
||||
<artifactId>smack-core</artifactId>
|
||||
<version>4.0.7</version>
|
||||
<version>4.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.paho</groupId>
|
||||
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.bwssytems</groupId>
|
||||
<artifactId>lifx-sdk-java</artifactId>
|
||||
<version>2.1.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.mob41</groupId>
|
||||
<artifactId>broadlink-java-api</artifactId>
|
||||
<version>master-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
@@ -151,6 +157,14 @@
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.1</version>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.bwssystems.HABridge;
|
||||
|
||||
import spark.Request;
|
||||
|
||||
public abstract class AuthFramework {
|
||||
private static final String USER_SESSION_ID = "user";
|
||||
|
||||
public AuthFramework() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public void addAuthenticatedUser(Request request, User u) {
|
||||
request.session().attribute(USER_SESSION_ID, u);
|
||||
|
||||
}
|
||||
|
||||
public void removeAuthenticatedUser(Request request) {
|
||||
request.session().removeAttribute(USER_SESSION_ID);
|
||||
|
||||
}
|
||||
|
||||
public User getAuthenticatedUser(Request request) {
|
||||
return request.session().attribute(USER_SESSION_ID);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,12 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.UUID;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
@@ -15,23 +21,36 @@ import javax.crypto.spec.PBEParameterSpec;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.api.hue.HueError;
|
||||
import com.bwssystems.HABridge.api.hue.HueErrorResponse;
|
||||
import com.bwssystems.HABridge.api.hue.WhitelistEntry;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
public class BridgeSecurity extends AuthFramework {
|
||||
import spark.Request;
|
||||
|
||||
public class BridgeSecurity {
|
||||
private static final Logger log = LoggerFactory.getLogger(BridgeSecurity.class);
|
||||
private char[] habridgeKey;
|
||||
private static final String USER_SESSION_ID = "user";
|
||||
private static final String DEPRACATED_INTERNAL_USER = "thehabridgeuser";
|
||||
private static final String TEST_USER_TYPE = "test_ha_bridge";
|
||||
private static final byte[] SALT = {
|
||||
(byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
|
||||
(byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
|
||||
};
|
||||
private char[] habridgeKey;
|
||||
private String execGarden;
|
||||
private BridgeSecurityDescriptor securityDescriptor;
|
||||
private boolean settingsChanged;
|
||||
|
||||
public BridgeSecurity(char[] theKey, String theData) {
|
||||
public BridgeSecurity(char[] theKey, String theExecGarden) {
|
||||
habridgeKey = theKey;
|
||||
execGarden = theExecGarden;
|
||||
securityDescriptor = null;
|
||||
settingsChanged = false;
|
||||
}
|
||||
|
||||
public void setSecurityData(String theData) {
|
||||
String anError = null;
|
||||
if(theData != null && !theData.isEmpty()) {
|
||||
try {
|
||||
@@ -43,7 +62,8 @@ public class BridgeSecurity extends AuthFramework {
|
||||
} catch (IOException e) {
|
||||
anError = e.getMessage();
|
||||
}
|
||||
log.warn("Cound not get security data, using default security (none): " + anError);
|
||||
if(anError != null)
|
||||
log.warn("Cound not get security data, using default security (none): " + anError);
|
||||
}
|
||||
|
||||
if(theData == null || anError != null) {
|
||||
@@ -123,13 +143,8 @@ public class BridgeSecurity extends AuthFramework {
|
||||
return error;
|
||||
}
|
||||
|
||||
public void setExecGarden(String theGarden) {
|
||||
securityDescriptor.setExecGarden(theGarden);
|
||||
settingsChanged = true;
|
||||
}
|
||||
|
||||
public String getExecGarden() {
|
||||
return securityDescriptor.getExecGarden();
|
||||
return execGarden;
|
||||
}
|
||||
public void setUseLinkButton(boolean useThis) {
|
||||
securityDescriptor.setUseLinkButton(useThis);
|
||||
@@ -145,7 +160,6 @@ public class BridgeSecurity extends AuthFramework {
|
||||
}
|
||||
public SecurityInfo getSecurityInfo() {
|
||||
SecurityInfo theInfo = new SecurityInfo();
|
||||
theInfo.setExecGarden(getExecGarden());
|
||||
theInfo.setUseLinkButton(isUseLinkButton());
|
||||
theInfo.setSecureHueApi(isSecureHueApi());
|
||||
theInfo.setSecure(isSecure());
|
||||
@@ -187,6 +201,128 @@ public class BridgeSecurity extends AuthFramework {
|
||||
public void setSettingsChanged(boolean settingsChanged) {
|
||||
this.settingsChanged = settingsChanged;
|
||||
}
|
||||
public Map<String, WhitelistEntry> getWhitelist() {
|
||||
return securityDescriptor.getWhitelist();
|
||||
}
|
||||
|
||||
public void setWhitelist(Map<String, WhitelistEntry> aWhitelist) {
|
||||
securityDescriptor.setWhitelist(aWhitelist);
|
||||
settingsChanged = true;
|
||||
return;
|
||||
}
|
||||
|
||||
public HueError[] validateWhitelistUser(String aUser, String userDescription, boolean strict) {
|
||||
String validUser = null;
|
||||
boolean found = false;
|
||||
if (aUser != null && !aUser.equalsIgnoreCase("undefined") && !aUser.equalsIgnoreCase("null")
|
||||
&& !aUser.equalsIgnoreCase("") && !aUser.equals(DEPRACATED_INTERNAL_USER)) {
|
||||
if (securityDescriptor.getWhitelist() != null) {
|
||||
Set<String> theUserIds = securityDescriptor.getWhitelist().keySet();
|
||||
Iterator<String> userIterator = theUserIds.iterator();
|
||||
while (userIterator.hasNext()) {
|
||||
validUser = userIterator.next();
|
||||
if (validUser.equals(aUser)) {
|
||||
found = true;
|
||||
log.debug("validateWhitelistUser: found a user <" + aUser + ">");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!found && !strict) {
|
||||
log.debug("validateWhitelistUser: a user was not found and it is not strict rules <" + aUser + "> being created");
|
||||
newWhitelistUser(aUser, userDescription);
|
||||
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
log.debug("validateWhitelistUser: a user was not found and strict rules is set to: " + strict + "for user <" + aUser + ">");
|
||||
return HueErrorResponse.createResponse("1", "/api/" + aUser == null ? "" : aUser, "unauthorized user", null, null, null).getTheErrors();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String findWhitelistUserByDeviceType(String aDeviceType) {
|
||||
String validUser = null;
|
||||
boolean found = false;
|
||||
WhitelistEntry anEntry = null;
|
||||
if (aDeviceType != null) {
|
||||
if (securityDescriptor.getWhitelist() != null) {
|
||||
Set<String> theUserIds = securityDescriptor.getWhitelist().keySet();
|
||||
Iterator<String> userIterator = theUserIds.iterator();
|
||||
while (!found && userIterator.hasNext()) {
|
||||
validUser = userIterator.next();
|
||||
anEntry = securityDescriptor.getWhitelist().get(validUser);
|
||||
if (anEntry.getName().equals(aDeviceType)) {
|
||||
found = true;
|
||||
log.debug("findWhitelistUserByDeviceType: found a user <" + validUser + "> for device type <" + aDeviceType + ">");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!found)
|
||||
validUser = null;
|
||||
|
||||
return validUser;
|
||||
}
|
||||
|
||||
private void newWhitelistUser(String aUser, String userDescription) {
|
||||
if (securityDescriptor.getWhitelist() == null) {
|
||||
securityDescriptor.setWhitelist(new HashMap<>());
|
||||
}
|
||||
if(userDescription == null)
|
||||
userDescription = "auto insert user";
|
||||
|
||||
securityDescriptor.getWhitelist().put(aUser, WhitelistEntry.createEntry(userDescription));
|
||||
setSettingsChanged(true);
|
||||
}
|
||||
|
||||
public String createWhitelistUser(String userDescription) {
|
||||
String aUser = null;
|
||||
String theEntry = findWhitelistUserByDeviceType(userDescription);
|
||||
if(theEntry == null) {
|
||||
aUser = getNewUserID();
|
||||
newWhitelistUser(aUser, userDescription);
|
||||
} else {
|
||||
aUser = theEntry;
|
||||
}
|
||||
return aUser;
|
||||
}
|
||||
|
||||
public void convertWhitelist(Map<String, WhitelistEntry> whitelist) {
|
||||
securityDescriptor.setWhitelist(whitelist);
|
||||
}
|
||||
|
||||
private String getNewUserID() {
|
||||
UUID uid = UUID.randomUUID();
|
||||
StringTokenizer st = new StringTokenizer(uid.toString(), "-");
|
||||
String newUser = "";
|
||||
while (st.hasMoreTokens()) {
|
||||
newUser = newUser + st.nextToken();
|
||||
}
|
||||
|
||||
return newUser;
|
||||
}
|
||||
|
||||
public void removeTestUsers() {
|
||||
if (securityDescriptor.getWhitelist() != null) {
|
||||
Object anUser = securityDescriptor.getWhitelist().remove(DEPRACATED_INTERNAL_USER);
|
||||
if(anUser != null)
|
||||
setSettingsChanged(true);
|
||||
|
||||
Iterator<Entry<String, WhitelistEntry>> it = securityDescriptor.getWhitelist().entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<String, WhitelistEntry> pair = it.next();
|
||||
if(pair.getValue().getName().equals(TEST_USER_TYPE)) {
|
||||
it.remove(); // avoids a ConcurrentModificationException
|
||||
setSettingsChanged(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String encrypt(String property) throws GeneralSecurityException, UnsupportedEncodingException {
|
||||
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
|
||||
@@ -211,4 +347,47 @@ public class BridgeSecurity extends AuthFramework {
|
||||
private static byte[] base64Decode(String property) throws IOException {
|
||||
return Base64.getDecoder().decode(property);
|
||||
}
|
||||
}
|
||||
|
||||
public void addAuthenticatedUser(Request request, User u) {
|
||||
request.session().attribute(USER_SESSION_ID, u);
|
||||
|
||||
}
|
||||
|
||||
public void removeAuthenticatedUser(Request request) {
|
||||
request.session().removeAttribute(USER_SESSION_ID);
|
||||
|
||||
}
|
||||
|
||||
public User getAuthenticatedUser(Request request) {
|
||||
User theUser = request.session().attribute(USER_SESSION_ID);
|
||||
if(theUser == null) {
|
||||
String authHeader = request.headers("Authorization");
|
||||
if(authHeader != null) {
|
||||
byte[] authData;
|
||||
try {
|
||||
authData = base64Decode(authHeader.substring(6));
|
||||
} catch (IOException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
return theUser;
|
||||
}
|
||||
String[] credentials = new String(authData).split(":");
|
||||
String username = credentials[0];
|
||||
String password = credentials[1];
|
||||
theUser = new User();
|
||||
theUser.setUsername(username);
|
||||
theUser.setPassword(password);
|
||||
LoginResult theResult = null;
|
||||
try {
|
||||
theResult = validatePassword(theUser);
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
return null;
|
||||
}
|
||||
if(theResult != null && theResult.getError() == null) {
|
||||
addAuthenticatedUser(request, theUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
return theUser;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.bwssystems.HABridge;
|
||||
|
||||
import java.util.Map;
|
||||
import com.bwssystems.HABridge.api.hue.WhitelistEntry;
|
||||
|
||||
public class BridgeSecurityDescriptor {
|
||||
private Map<String, User> users;
|
||||
private boolean useLinkButton;
|
||||
private String execGarden;
|
||||
private boolean secureHueApi;
|
||||
private Map<String, WhitelistEntry> whitelist;
|
||||
|
||||
public BridgeSecurityDescriptor() {
|
||||
super();
|
||||
@@ -44,6 +46,12 @@ public class BridgeSecurityDescriptor {
|
||||
public void setSecureHueApi(boolean secureHueApi) {
|
||||
this.secureHueApi = secureHueApi;
|
||||
}
|
||||
public Map<String, WhitelistEntry> getWhitelist() {
|
||||
return whitelist;
|
||||
}
|
||||
public void setWhitelist(Map<String, WhitelistEntry> whitelist) {
|
||||
this.whitelist = whitelist;
|
||||
}
|
||||
|
||||
public boolean isSecure() {
|
||||
boolean secureFlag = false;
|
||||
|
||||
@@ -12,6 +12,8 @@ import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.nio.file.attribute.PosixFilePermission;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -22,6 +24,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.util.BackupHandler;
|
||||
import com.bwssystems.HABridge.util.JsonTransformer;
|
||||
import com.bwssystems.HABridge.util.ParseRoute;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class BridgeSettings extends BackupHandler {
|
||||
@@ -29,12 +32,18 @@ public class BridgeSettings extends BackupHandler {
|
||||
private BridgeSettingsDescriptor theBridgeSettings;
|
||||
private BridgeControlDescriptor bridgeControl;
|
||||
private BridgeSecurity bridgeSecurity;
|
||||
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
|
||||
|
||||
public BridgeSettings() {
|
||||
super();
|
||||
bridgeControl = new BridgeControlDescriptor();
|
||||
theBridgeSettings = new BridgeSettingsDescriptor();
|
||||
bridgeSecurity = null;
|
||||
String theKey = System.getProperty("security.key");
|
||||
if(theKey == null)
|
||||
theKey = "IWantMyPasswordsToBeAbleToBeDecodedPleaseSeeTheReadme";
|
||||
String execGarden = System.getProperty("exec.garden");
|
||||
bridgeSecurity = new BridgeSecurity(theKey.toCharArray(), execGarden);
|
||||
String ipV6Stack = System.getProperty("ipV6Stack");
|
||||
if(ipV6Stack == null || !ipV6Stack.equalsIgnoreCase("true")) {
|
||||
System.setProperty("java.net.preferIPv4Stack" , "true");
|
||||
@@ -50,9 +59,14 @@ public class BridgeSettings extends BackupHandler {
|
||||
public BridgeSecurity getBridgeSecurity() {
|
||||
return bridgeSecurity;
|
||||
}
|
||||
public static String getCurrentDate() {
|
||||
return dateFormat.format(new Date());
|
||||
}
|
||||
|
||||
public void buildSettings() {
|
||||
String addressString = null;
|
||||
String theVeraAddress = null;
|
||||
String theFibaroAddress = null;
|
||||
String theSomfyAddress = null;
|
||||
String theHarmonyAddress = null;
|
||||
String configFileProperty = System.getProperty("config.file");
|
||||
@@ -63,6 +77,7 @@ public class BridgeSettings extends BackupHandler {
|
||||
}
|
||||
String serverPortOverride = System.getProperty("server.port");
|
||||
String serverIpOverride = System.getProperty("server.ip");
|
||||
String upnpStrictOverride = System.getProperty("upnp.strict", "true");
|
||||
if(configFileProperty != null)
|
||||
{
|
||||
log.info("reading from config file: " + configFileProperty);
|
||||
@@ -78,6 +93,7 @@ public class BridgeSettings extends BackupHandler {
|
||||
theBridgeSettings.setServerPort(System.getProperty("server.port", Configuration.DEFAULT_WEB_PORT));
|
||||
theBridgeSettings.setUpnpConfigAddress(System.getProperty("upnp.config.address"));
|
||||
theBridgeSettings.setUpnpDeviceDb(System.getProperty("upnp.device.db"));
|
||||
theBridgeSettings.setUpnpGroupDb(System.getProperty("upnp.group.db"));
|
||||
theBridgeSettings.setUpnpResponsePort(System.getProperty("upnp.response.port", Configuration.UPNP_RESPONSE_PORT));
|
||||
|
||||
theVeraAddress = System.getProperty("vera.address");
|
||||
@@ -95,6 +111,22 @@ public class BridgeSettings extends BackupHandler {
|
||||
}
|
||||
}
|
||||
theBridgeSettings.setVeraAddress(theVeraList);
|
||||
|
||||
theFibaroAddress = System.getProperty("fibaro.address");
|
||||
IpList theFibaroList = null;
|
||||
if(theFibaroAddress != null) {
|
||||
try {
|
||||
theFibaroList = new Gson().fromJson(theFibaroAddress, IpList.class);
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
theFibaroList = new Gson().fromJson("{devices:[{name:default,ip:" + theFibaroAddress + "}]}", IpList.class);
|
||||
} catch (Exception et) {
|
||||
log.error("Cannot parse fibaro.address, not set with message: " + e.getMessage(), e);
|
||||
theFibaroList = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
theBridgeSettings.setFibaroAddress(theFibaroList);
|
||||
|
||||
theHarmonyAddress = System.getProperty("harmony.address");
|
||||
IpList theHarmonyList = null;
|
||||
@@ -135,8 +167,9 @@ public class BridgeSettings extends BackupHandler {
|
||||
theBridgeSettings.setNestpwd(System.getProperty("nest.pwd"));
|
||||
}
|
||||
|
||||
if(theBridgeSettings.getUpnpConfigAddress() == null || theBridgeSettings.getUpnpConfigAddress().equals("")) {
|
||||
addressString = checkIpAddress(null, true);
|
||||
ParseRoute aDefaultRoute = ParseRoute.getInstance();
|
||||
if(theBridgeSettings.getUpnpConfigAddress() == null || theBridgeSettings.getUpnpConfigAddress().trim().equals("") || theBridgeSettings.getUpnpConfigAddress().trim().equals("0.0.0.0")) {
|
||||
addressString = aDefaultRoute.getLocalIPAddress();
|
||||
if(addressString != null) {
|
||||
theBridgeSettings.setUpnpConfigAddress(addressString);
|
||||
log.info("Adding " + addressString + " as our default upnp config address.");
|
||||
@@ -146,8 +179,10 @@ public class BridgeSettings extends BackupHandler {
|
||||
}
|
||||
else {
|
||||
addressString = checkIpAddress(theBridgeSettings.getUpnpConfigAddress(), false);
|
||||
if(addressString == null)
|
||||
log.warn("The upnp config address, " + theBridgeSettings.getUpnpConfigAddress() + ", does not match any known IP's on this host.");
|
||||
if(addressString == null) {
|
||||
addressString = aDefaultRoute.getLocalIPAddress();
|
||||
log.warn("The upnp config address, " + theBridgeSettings.getUpnpConfigAddress() + ", does not match any known IP's on this host. Using default address: " + addressString);
|
||||
}
|
||||
}
|
||||
|
||||
if(theBridgeSettings.getUpnpResponsePort() == null)
|
||||
@@ -158,6 +193,9 @@ public class BridgeSettings extends BackupHandler {
|
||||
|
||||
if(theBridgeSettings.getUpnpDeviceDb() == null)
|
||||
theBridgeSettings.setUpnpDeviceDb(Configuration.DEVICE_DB_DIRECTORY);
|
||||
|
||||
if(theBridgeSettings.getUpnpGroupDb() == null)
|
||||
theBridgeSettings.setUpnpGroupDb(Configuration.GROUP_DB_DIRECTORY);
|
||||
|
||||
if(theBridgeSettings.getNumberoflogmessages() == null || theBridgeSettings.getNumberoflogmessages() <= 0)
|
||||
theBridgeSettings.setNumberoflogmessages(new Integer(Configuration.NUMBER_OF_LOG_MESSAGES));
|
||||
@@ -166,6 +204,7 @@ public class BridgeSettings extends BackupHandler {
|
||||
theBridgeSettings.setButtonsleep(Integer.parseInt(Configuration.DEFAULT_BUTTON_SLEEP));
|
||||
|
||||
theBridgeSettings.setVeraconfigured(theBridgeSettings.isValidVera());
|
||||
theBridgeSettings.setFibaroconfigured(theBridgeSettings.isValidFibaro());
|
||||
theBridgeSettings.setHarmonyconfigured(theBridgeSettings.isValidHarmony());
|
||||
theBridgeSettings.setNestConfigured(theBridgeSettings.isValidNest());
|
||||
theBridgeSettings.setHueconfigured(theBridgeSettings.isValidHue());
|
||||
@@ -174,19 +213,26 @@ public class BridgeSettings extends BackupHandler {
|
||||
theBridgeSettings.setHassconfigured(theBridgeSettings.isValidHass());
|
||||
theBridgeSettings.setDomoticzconfigured(theBridgeSettings.isValidDomoticz());
|
||||
theBridgeSettings.setSomfyconfigured(theBridgeSettings.isValidSomfy());
|
||||
theBridgeSettings.setHomeWizardConfigured(theBridgeSettings.isValidHomeWizard());
|
||||
theBridgeSettings.setOpenhabconfigured(theBridgeSettings.isValidOpenhab());
|
||||
theBridgeSettings.setFhemconfigured(theBridgeSettings.isValidFhem());
|
||||
// Lifx is either configured or not, so it does not need an update.
|
||||
if(serverPortOverride != null)
|
||||
theBridgeSettings.setServerPort(serverPortOverride);
|
||||
if(serverIpOverride != null)
|
||||
if(serverIpOverride != null) {
|
||||
theBridgeSettings.setWebaddress(serverIpOverride);
|
||||
theBridgeSettings.setUpnpConfigAddress(serverIpOverride);
|
||||
}
|
||||
if(upnpStrictOverride != null)
|
||||
theBridgeSettings.setUpnpStrict(Boolean.parseBoolean(upnpStrictOverride));
|
||||
setupParams(Paths.get(theBridgeSettings.getConfigfile()), ".cfgbk", "habridge.config-");
|
||||
|
||||
setupInternalTestUser();
|
||||
|
||||
String theKey = System.getProperty("security.key");
|
||||
if(theKey == null)
|
||||
theKey = "IWantMyPasswordsToBeAbleToBeDecodedPleaseSeeTheReadme";
|
||||
bridgeSecurity = new BridgeSecurity(theKey.toCharArray(), theBridgeSettings.getSecurityData());
|
||||
bridgeSecurity.setSecurityData(theBridgeSettings.getSecurityData());
|
||||
if(theBridgeSettings.getWhitelist() != null) {
|
||||
bridgeSecurity.convertWhitelist(theBridgeSettings.getWhitelist());
|
||||
theBridgeSettings.removeWhitelist();
|
||||
updateConfigFile();
|
||||
}
|
||||
}
|
||||
|
||||
public void loadConfig() {
|
||||
@@ -219,11 +265,11 @@ public class BridgeSettings extends BackupHandler {
|
||||
try {
|
||||
newBridgeSettings.setSecurityData(bridgeSecurity.getSecurityDescriptorData());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
log.warn("could not get encoded security data: " + e.getMessage());
|
||||
return;
|
||||
} catch (GeneralSecurityException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
log.warn("could not get encoded security data: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
bridgeSecurity.setSettingsChanged(false);
|
||||
}
|
||||
@@ -237,13 +283,25 @@ public class BridgeSettings extends BackupHandler {
|
||||
log.debug("Save HA Bridge settings.");
|
||||
Path configPath = Paths.get(theBridgeSettings.getConfigfile());
|
||||
JsonTransformer aRenderer = new JsonTransformer();
|
||||
if(bridgeSecurity.isSettingsChanged()) {
|
||||
try {
|
||||
theBridgeSettings.setSecurityData(bridgeSecurity.getSecurityDescriptorData());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
log.warn("could not get encoded security data: " + e.getMessage());
|
||||
return;
|
||||
} catch (GeneralSecurityException e) {
|
||||
log.warn("could not get encoded security data: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
bridgeSecurity.setSettingsChanged(false);
|
||||
}
|
||||
String jsonValue = aRenderer.render(theBridgeSettings);
|
||||
configWriter(jsonValue, configPath);
|
||||
_loadConfig(configPath);
|
||||
}
|
||||
|
||||
|
||||
private void configWriter(String content, Path filePath) {
|
||||
private synchronized void configWriter(String content, Path filePath) {
|
||||
if(Files.exists(filePath) && !Files.isWritable(filePath)){
|
||||
log.error("Error file is not writable: " + filePath);
|
||||
return;
|
||||
@@ -260,7 +318,7 @@ public class BridgeSettings extends BackupHandler {
|
||||
try {
|
||||
Path target = null;
|
||||
if(Files.exists(filePath)) {
|
||||
target = FileSystems.getDefault().getPath(filePath.getParent().toString(), "habridge.config.old");
|
||||
target = FileSystems.getDefault().getPath(filePath.getParent().toString(), "habridge.config.old." + getCurrentDate());
|
||||
Files.move(filePath, target);
|
||||
}
|
||||
Files.write(filePath, content.getBytes(), StandardOpenOption.CREATE);
|
||||
@@ -273,7 +331,8 @@ public class BridgeSettings extends BackupHandler {
|
||||
perms.add(PosixFilePermission.OWNER_WRITE);
|
||||
|
||||
try {
|
||||
if(System.getProperty("os.name").toLowerCase().indexOf("win") <= 0)
|
||||
String osName = System.getProperty("os.name");
|
||||
if(osName.toLowerCase().indexOf("win") < 0)
|
||||
Files.setPosixFilePermissions(filePath, perms);
|
||||
} catch(UnsupportedOperationException e) {
|
||||
log.info("Cannot set permissions for config file on this system as it is not supported. Continuing");
|
||||
@@ -309,6 +368,7 @@ public class BridgeSettings extends BackupHandler {
|
||||
log.error("checkIpAddress cannot get ip address of this host, Exiting with message: " + e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
|
||||
String addressString = null;
|
||||
InetAddress address = null;
|
||||
while (ifs.hasMoreElements() && addressString == null) {
|
||||
@@ -335,9 +395,4 @@ public class BridgeSettings extends BackupHandler {
|
||||
}
|
||||
return addressString;
|
||||
}
|
||||
private void setupInternalTestUser() {
|
||||
theBridgeSettings.setupInternalTestUser();
|
||||
if(theBridgeSettings.isSettingsChanged())
|
||||
this.updateConfigFile();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,77 +1,171 @@
|
||||
package com.bwssystems.HABridge;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
//import com.bwssystems.HABridge.api.NameValue;
|
||||
import com.bwssystems.HABridge.api.hue.HueConstants;
|
||||
import com.bwssystems.HABridge.api.hue.HueError;
|
||||
import com.bwssystems.HABridge.api.hue.HueErrorResponse;
|
||||
import com.bwssystems.HABridge.api.hue.WhitelistEntry;
|
||||
|
||||
public class BridgeSettingsDescriptor {
|
||||
private static final String DEFAULT_INTERNAL_USER = "thehabridgeuser";
|
||||
private static final String DEFAULT_USER_DESCRIPTION = "default_test_user";
|
||||
@SerializedName("upnpconfigaddress")
|
||||
@Expose
|
||||
private String upnpconfigaddress;
|
||||
@SerializedName("useupnpiface")
|
||||
@Expose
|
||||
private boolean useupnpiface;
|
||||
@SerializedName("userooms")
|
||||
@Expose
|
||||
private boolean userooms;
|
||||
@SerializedName("serverport")
|
||||
@Expose
|
||||
private Integer serverport;
|
||||
@SerializedName("upnpresponseport")
|
||||
@Expose
|
||||
private Integer upnpresponseport;
|
||||
@SerializedName("upnpdevicedb")
|
||||
@Expose
|
||||
private String upnpdevicedb;
|
||||
@SerializedName("upnpgroupdb")
|
||||
@Expose
|
||||
private String upnpgroupdb;
|
||||
@SerializedName("veraaddress")
|
||||
@Expose
|
||||
private IpList veraaddress;
|
||||
@SerializedName("fibaroaddress")
|
||||
@Expose
|
||||
private IpList fibaroaddress;
|
||||
@SerializedName("harmonyaddress")
|
||||
@Expose
|
||||
private IpList harmonyaddress;
|
||||
@SerializedName("buttonsleep")
|
||||
@Expose
|
||||
private Integer buttonsleep;
|
||||
private boolean upnpstrict;
|
||||
@SerializedName("traceupnp")
|
||||
@Expose
|
||||
private boolean traceupnp;
|
||||
@SerializedName("nestuser")
|
||||
@Expose
|
||||
private String nestuser;
|
||||
@SerializedName("nestpwd")
|
||||
@Expose
|
||||
private String nestpwd;
|
||||
private boolean veraconfigured;
|
||||
private boolean harmonyconfigured;
|
||||
private boolean nestconfigured;
|
||||
@SerializedName("farenheit")
|
||||
@Expose
|
||||
private boolean farenheit;
|
||||
@SerializedName("configfile")
|
||||
@Expose
|
||||
private String configfile;
|
||||
@SerializedName("numberoflogmessages")
|
||||
@Expose
|
||||
private Integer numberoflogmessages;
|
||||
@SerializedName("hueaddress")
|
||||
@Expose
|
||||
private IpList hueaddress;
|
||||
private boolean hueconfigured;
|
||||
@SerializedName("haladdress")
|
||||
@Expose
|
||||
private IpList haladdress;
|
||||
private String haltoken;
|
||||
private boolean halconfigured;
|
||||
@SerializedName("whitelist")
|
||||
@Expose
|
||||
private Map<String, WhitelistEntry> whitelist;
|
||||
private boolean settingsChanged;
|
||||
@SerializedName("myechourl")
|
||||
@Expose
|
||||
private String myechourl;
|
||||
@SerializedName("webaddress")
|
||||
@Expose
|
||||
private String webaddress;
|
||||
@SerializedName("mqttaddress")
|
||||
@Expose
|
||||
private IpList mqttaddress;
|
||||
private boolean mqttconfigured;
|
||||
@SerializedName("hassaddress")
|
||||
@Expose
|
||||
private IpList hassaddress;
|
||||
private boolean hassconfigured;
|
||||
private String hubversion;
|
||||
@SerializedName("domoticzaddress")
|
||||
@Expose
|
||||
private IpList domoticzaddress;
|
||||
private boolean domoticzconfigured;
|
||||
@SerializedName("somfyaddress")
|
||||
@Expose
|
||||
private IpList somfyaddress;
|
||||
private boolean somfyconfigured;
|
||||
private boolean lifxconfigured;
|
||||
@SerializedName("openhabaddress")
|
||||
@Expose
|
||||
private IpList openhabaddress;
|
||||
@SerializedName("hubversion")
|
||||
@Expose
|
||||
private String hubversion;
|
||||
@SerializedName("hubmac")
|
||||
@Expose
|
||||
private String hubmac;
|
||||
@SerializedName("securityData")
|
||||
@Expose
|
||||
private String securityData;
|
||||
@SerializedName("homewizardaddress")
|
||||
@Expose
|
||||
private IpList homewizardaddress;
|
||||
@SerializedName("upnpsenddelay")
|
||||
@Expose
|
||||
private Integer upnpsenddelay;
|
||||
@SerializedName("fhemaddress")
|
||||
@Expose
|
||||
private IpList fhemaddress;
|
||||
@SerializedName("lifxconfigured")
|
||||
@Expose
|
||||
private boolean lifxconfigured;
|
||||
@SerializedName("broadlinkconfigured")
|
||||
@Expose
|
||||
private boolean broadlinkconfigured;
|
||||
// @SerializedName("activeloggers")
|
||||
// @Expose
|
||||
// private List<NameValue> activeloggers;
|
||||
|
||||
private boolean settingsChanged;
|
||||
private boolean veraconfigured;
|
||||
private boolean fibaroconfigured;
|
||||
private boolean harmonyconfigured;
|
||||
private boolean hueconfigured;
|
||||
private boolean nestconfigured;
|
||||
private boolean halconfigured;
|
||||
private boolean mqttconfigured;
|
||||
private boolean hassconfigured;
|
||||
private boolean domoticzconfigured;
|
||||
private boolean somfyconfigured;
|
||||
private boolean homewizardconfigured;
|
||||
private boolean openhabconfigured;
|
||||
private boolean fhemconfigured;
|
||||
|
||||
// Deprecated settings
|
||||
private String haltoken;
|
||||
private boolean upnpstrict;
|
||||
|
||||
public BridgeSettingsDescriptor() {
|
||||
super();
|
||||
this.upnpstrict = true;
|
||||
this.useupnpiface = false;
|
||||
this.userooms = false;
|
||||
this.traceupnp = false;
|
||||
this.nestconfigured = false;
|
||||
this.veraconfigured = false;
|
||||
this.fibaroconfigured = false;
|
||||
this.somfyconfigured = false;
|
||||
this.harmonyconfigured = false;
|
||||
this.hueconfigured = false;
|
||||
this.halconfigured = false;
|
||||
this.mqttconfigured = false;
|
||||
this.hassconfigured = false;
|
||||
this.domoticzconfigured = false;
|
||||
this.homewizardconfigured = false;
|
||||
this.lifxconfigured = false;
|
||||
this.openhabconfigured = false;
|
||||
this.farenheit = true;
|
||||
this.whitelist = null;
|
||||
this.securityData = null;
|
||||
this.settingsChanged = false;
|
||||
this.myechourl = "echo.amazon.com/#cards";
|
||||
this.myechourl = "alexa.amazon.com/spa/index.html#cards";
|
||||
this.webaddress = "0.0.0.0";
|
||||
this.hubversion = HueConstants.HUB_VERSION;
|
||||
this.hubmac = null;
|
||||
// this.activeloggers = null;
|
||||
this.upnpsenddelay = Configuration.UPNP_SEND_DELAY;
|
||||
this.broadlinkconfigured = false;
|
||||
}
|
||||
public String getUpnpConfigAddress() {
|
||||
return upnpconfigaddress;
|
||||
@@ -79,6 +173,18 @@ public class BridgeSettingsDescriptor {
|
||||
public void setUpnpConfigAddress(String upnpConfigAddress) {
|
||||
this.upnpconfigaddress = upnpConfigAddress;
|
||||
}
|
||||
public boolean isUseupnpiface() {
|
||||
return useupnpiface;
|
||||
}
|
||||
public void setUseupnpiface(boolean useupnpiface) {
|
||||
this.useupnpiface = useupnpiface;
|
||||
}
|
||||
public boolean isUserooms() {
|
||||
return userooms;
|
||||
}
|
||||
public void setUserooms(boolean userooms) {
|
||||
this.userooms = userooms;
|
||||
}
|
||||
public Integer getServerPort() {
|
||||
return serverport;
|
||||
}
|
||||
@@ -103,18 +209,36 @@ public class BridgeSettingsDescriptor {
|
||||
public void setUpnpDeviceDb(String upnpDeviceDb) {
|
||||
this.upnpdevicedb = upnpDeviceDb;
|
||||
}
|
||||
public String getUpnpGroupDb() {
|
||||
return upnpgroupdb;
|
||||
}
|
||||
public void setUpnpGroupDb(String upnpGroupDb) {
|
||||
this.upnpgroupdb = upnpGroupDb;
|
||||
}
|
||||
public IpList getVeraAddress() {
|
||||
return veraaddress;
|
||||
}
|
||||
public IpList getFibaroAddress() {
|
||||
return fibaroaddress;
|
||||
}
|
||||
public IpList getSomfyAddress() {
|
||||
return somfyaddress;
|
||||
}
|
||||
public IpList getHomeWizardAddress() {
|
||||
return homewizardaddress;
|
||||
}
|
||||
public void setVeraAddress(IpList veraAddress) {
|
||||
this.veraaddress = veraAddress;
|
||||
}
|
||||
public void setFibaroAddress(IpList fibaroAddress) {
|
||||
this.fibaroaddress = fibaroAddress;
|
||||
}
|
||||
public void setSomfyAddress(IpList somfyAddress) {
|
||||
this.somfyaddress = somfyAddress;
|
||||
}
|
||||
public void setHomeWizardAddress(IpList homewizardaddress) {
|
||||
this.homewizardaddress = homewizardaddress;
|
||||
}
|
||||
public IpList getHarmonyAddress() {
|
||||
return harmonyaddress;
|
||||
}
|
||||
@@ -148,15 +272,27 @@ public class BridgeSettingsDescriptor {
|
||||
public boolean isVeraconfigured() {
|
||||
return veraconfigured;
|
||||
}
|
||||
public boolean isFibaroconfigured() {
|
||||
return fibaroconfigured;
|
||||
}
|
||||
public boolean isSomfyconfigured() {
|
||||
return somfyconfigured;
|
||||
}
|
||||
public boolean isHomeWizardConfigured() {
|
||||
return homewizardconfigured;
|
||||
}
|
||||
public void setVeraconfigured(boolean veraconfigured) {
|
||||
this.veraconfigured = veraconfigured;
|
||||
}
|
||||
public void setFibaroconfigured(boolean fibaroconfigured) {
|
||||
this.fibaroconfigured = fibaroconfigured;
|
||||
}
|
||||
public void setSomfyconfigured(boolean somfyconfigured) {
|
||||
this.somfyconfigured = somfyconfigured;
|
||||
}
|
||||
public void setHomeWizardConfigured(boolean homewizardconfigured) {
|
||||
this.homewizardconfigured = homewizardconfigured;
|
||||
}
|
||||
public boolean isHarmonyconfigured() {
|
||||
return harmonyconfigured;
|
||||
}
|
||||
@@ -226,8 +362,8 @@ public class BridgeSettingsDescriptor {
|
||||
public Map<String, WhitelistEntry> getWhitelist() {
|
||||
return whitelist;
|
||||
}
|
||||
public void setWhitelist(Map<String, WhitelistEntry> whitelist) {
|
||||
this.whitelist = whitelist;
|
||||
protected void removeWhitelist() {
|
||||
whitelist = null;
|
||||
}
|
||||
public boolean isSettingsChanged() {
|
||||
return settingsChanged;
|
||||
@@ -271,12 +407,30 @@ public class BridgeSettingsDescriptor {
|
||||
public void setHassconfigured(boolean hassconfigured) {
|
||||
this.hassconfigured = hassconfigured;
|
||||
}
|
||||
public IpList getOpenhabaddress() {
|
||||
return openhabaddress;
|
||||
}
|
||||
public void setOpenhabaddress(IpList openhabaddress) {
|
||||
this.openhabaddress = openhabaddress;
|
||||
}
|
||||
public boolean isOpenhabconfigured() {
|
||||
return openhabconfigured;
|
||||
}
|
||||
public void setOpenhabconfigured(boolean openhabconfigured) {
|
||||
this.openhabconfigured = openhabconfigured;
|
||||
}
|
||||
public String getHubversion() {
|
||||
return hubversion;
|
||||
}
|
||||
public void setHubversion(String hubversion) {
|
||||
this.hubversion = hubversion;
|
||||
}
|
||||
public String getHubmac() {
|
||||
return hubmac;
|
||||
}
|
||||
public void setHubmac(String hubmac) {
|
||||
this.hubmac = hubmac;
|
||||
}
|
||||
public IpList getDomoticzaddress() {
|
||||
return domoticzaddress;
|
||||
}
|
||||
@@ -301,6 +455,36 @@ public class BridgeSettingsDescriptor {
|
||||
public void setSecurityData(String securityData) {
|
||||
this.securityData = securityData;
|
||||
}
|
||||
public Integer getUpnpsenddelay() {
|
||||
return upnpsenddelay;
|
||||
}
|
||||
public void setUpnpsenddelay(Integer upnpsenddelay) {
|
||||
this.upnpsenddelay = upnpsenddelay;
|
||||
}
|
||||
public IpList getFhemaddress() {
|
||||
return fhemaddress;
|
||||
}
|
||||
public void setFhemaddress(IpList fhemaddress) {
|
||||
this.fhemaddress = fhemaddress;
|
||||
}
|
||||
public boolean isFhemconfigured() {
|
||||
return fhemconfigured;
|
||||
}
|
||||
public void setFhemconfigured(boolean fhemconfigured) {
|
||||
this.fhemconfigured = fhemconfigured;
|
||||
}
|
||||
// public List<NameValue> getActiveloggers() {
|
||||
// return activeloggers;
|
||||
// }
|
||||
// public void setActiveloggers(List<NameValue> activeloggers) {
|
||||
// this.activeloggers = activeloggers;
|
||||
// }
|
||||
public boolean isBroadlinkconfigured() {
|
||||
return broadlinkconfigured;
|
||||
}
|
||||
public void setBroadlinkconfigured(boolean broadlinkconfigured) {
|
||||
this.broadlinkconfigured = broadlinkconfigured;
|
||||
}
|
||||
public Boolean isValidVera() {
|
||||
if(this.getVeraAddress() == null || this.getVeraAddress().getDevices().size() <= 0)
|
||||
return false;
|
||||
@@ -309,6 +493,14 @@ public class BridgeSettingsDescriptor {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
public Boolean isValidFibaro() {
|
||||
if(this.getFibaroAddress() == null || this.getFibaroAddress().getDevices().size() <= 0)
|
||||
return false;
|
||||
List<NamedIP> devicesList = this.getFibaroAddress().getDevices();
|
||||
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
public Boolean isValidHarmony() {
|
||||
if(this.getHarmonyAddress() == null || this.getHarmonyAddress().getDevices().size() <= 0)
|
||||
return false;
|
||||
@@ -338,8 +530,10 @@ public class BridgeSettingsDescriptor {
|
||||
List<NamedIP> devicesList = this.getHaladdress().getDevices();
|
||||
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))
|
||||
return false;
|
||||
if(this.getHaltoken() == null || this.getHaltoken().equals(""))
|
||||
return false;
|
||||
if(devicesList.get(0).getPassword() == null || devicesList.get(0).getPassword().trim().isEmpty()) {
|
||||
if(this.getHaltoken() == null || this.getHaltoken().equals(""))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public Boolean isValidMQTT() {
|
||||
@@ -377,80 +571,48 @@ public class BridgeSettingsDescriptor {
|
||||
public Boolean isValidLifx() {
|
||||
return this.isLifxconfigured();
|
||||
}
|
||||
|
||||
public HueError[] validateWhitelistUser(String aUser, String userDescription, boolean strict) {
|
||||
String validUser = null;
|
||||
boolean found = false;
|
||||
if (aUser != null && !aUser.equalsIgnoreCase("undefined") && !aUser.equalsIgnoreCase("null")
|
||||
&& !aUser.equalsIgnoreCase("")) {
|
||||
if (whitelist != null) {
|
||||
Set<String> theUserIds = whitelist.keySet();
|
||||
Iterator<String> userIterator = theUserIds.iterator();
|
||||
while (userIterator.hasNext()) {
|
||||
validUser = userIterator.next();
|
||||
if (validUser.equals(aUser))
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
public void updateHue(NamedIP aHue) {
|
||||
int indexHue = -1;
|
||||
for( int i = 0; i < hueaddress.getDevices().size(); i++) {
|
||||
if(hueaddress.getDevices().get(i).getName().equals(aHue.getName()))
|
||||
indexHue = i;
|
||||
}
|
||||
|
||||
if(!found && !strict) {
|
||||
newWhitelistUser(aUser, userDescription);
|
||||
|
||||
found = true;
|
||||
if(indexHue >= 0) {
|
||||
hueaddress.getDevices().set(indexHue, aHue);
|
||||
this.setSettingsChanged(true);
|
||||
}
|
||||
}
|
||||
public Boolean isValidHomeWizard() {
|
||||
if(this.getHomeWizardAddress() == null || this.getHomeWizardAddress().getDevices().size() <= 0)
|
||||
return false;
|
||||
|
||||
if (!found) {
|
||||
return HueErrorResponse.createResponse("1", "/api/" + aUser, "unauthorized user", null, null, null).getTheErrors();
|
||||
}
|
||||
List<NamedIP> devicesList = this.getHomeWizardAddress().getDevices();
|
||||
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))
|
||||
return false;
|
||||
|
||||
return null;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void newWhitelistUser(String aUser, String userDescription) {
|
||||
if (whitelist == null) {
|
||||
whitelist = new HashMap<>();
|
||||
}
|
||||
if(userDescription == null)
|
||||
userDescription = "auto insert user";
|
||||
public Boolean isValidOpenhab() {
|
||||
if(this.getOpenhabaddress() == null || this.getOpenhabaddress().getDevices().size() <= 0)
|
||||
return false;
|
||||
|
||||
whitelist.put(aUser, WhitelistEntry.createEntry(userDescription));
|
||||
setSettingsChanged(true);
|
||||
List<NamedIP> devicesList = this.getOpenhabaddress().getDevices();
|
||||
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public String createWhitelistUser(String userDescription) {
|
||||
String aUser = getNewUserID();
|
||||
newWhitelistUser(aUser, userDescription);
|
||||
return aUser;
|
||||
public Boolean isValidFhem() {
|
||||
if(this.getFhemaddress() == null || this.getFhemaddress().getDevices().size() <= 0)
|
||||
return false;
|
||||
|
||||
List<NamedIP> devicesList = this.getFhemaddress().getDevices();
|
||||
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private String getNewUserID() {
|
||||
UUID uid = UUID.randomUUID();
|
||||
StringTokenizer st = new StringTokenizer(uid.toString(), "-");
|
||||
String newUser = "";
|
||||
while (st.hasMoreTokens()) {
|
||||
newUser = newUser + st.nextToken();
|
||||
}
|
||||
|
||||
return newUser;
|
||||
}
|
||||
|
||||
public String getInternalTestUser() {
|
||||
return DEFAULT_INTERNAL_USER;
|
||||
}
|
||||
|
||||
public void setupInternalTestUser() {
|
||||
boolean found = false;
|
||||
if(whitelist != null) {
|
||||
for (String key : whitelist.keySet()) {
|
||||
if(key.equals(DEFAULT_INTERNAL_USER)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
newWhitelistUser(DEFAULT_INTERNAL_USER, DEFAULT_USER_DESCRIPTION);
|
||||
}
|
||||
public Boolean isValidBroadlink() {
|
||||
return this.isBroadlinkconfigured();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.bwssystems.HABridge;
|
||||
|
||||
public class Configuration {
|
||||
public final static String DEVICE_DB_DIRECTORY = "data/device.db";
|
||||
public final static String GROUP_DB_DIRECTORY = "data/group.db";
|
||||
public final static String UPNP_RESPONSE_PORT = "50000";
|
||||
public final static String DEFAULT_ADDRESS = "1.1.1.1";
|
||||
public final static String LOOP_BACK_ADDRESS = "127.0.0.1";
|
||||
@@ -13,4 +14,7 @@ public class Configuration {
|
||||
public static final String CONFIG_FILE = "data/habridge.config";
|
||||
public static final int NUMBER_OF_LOG_MESSAGES = 512;
|
||||
public static final long UPNP_NOTIFY_TIMEOUT = 20000;
|
||||
public static final int UPNP_SEND_DELAY = 650;
|
||||
public static final int BROADLINK_DISCOVER_PORT = 40000;
|
||||
public static final int BROADLINK_DISCONVER_TIMEOUT = 5000;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ public class DeviceMapTypes {
|
||||
public final static String[] CUSTOM_DEVICE = { "custom", "Custom"};
|
||||
public final static String[] VERA_DEVICE = { "veraDevice", "Vera Device"};
|
||||
public final static String[] VERA_SCENE = { "veraScene", "Vera Scene"};
|
||||
public final static String[] FIBARO_DEVICE = { "fibaroDevice", "Fibaro Device"};
|
||||
public final static String[] FIBARO_SCENE = { "fibaroScene", "Fibaro Scene"};
|
||||
public final static String[] HARMONY_ACTIVITY = { "harmonyActivity", "Harmony Activity"};
|
||||
public final static String[] HARMONY_BUTTON = { "harmonyButton", "Harmony Button"};
|
||||
public final static String[] NEST_HOMEAWAY = { "nestHomeAway", "Nest Home Status"};
|
||||
@@ -20,6 +22,7 @@ public class DeviceMapTypes {
|
||||
public final static String[] EXEC_DEVICE_COMPAT = { "exec", "Execute Script/Program"};
|
||||
public final static String[] CMD_DEVICE = { "cmdDevice", "Execute Command/Script/Program"};
|
||||
public final static String[] HASS_DEVICE = { "hassDevice", "HomeAssistant Device"};
|
||||
public final static String[] HOMEWIZARD_DEVICE = { "homewizardDevice", "HomeWizard Device"};
|
||||
public final static String[] TCP_DEVICE = { "tcpDevice", "TCP Device"};
|
||||
public final static String[] TCP_DEVICE_COMPAT = { "TCP", "TCP Device"};
|
||||
public final static String[] UDP_DEVICE = { "udpDevice", "UDP Device"};
|
||||
@@ -28,6 +31,9 @@ public class DeviceMapTypes {
|
||||
public final static String[] DOMOTICZ_DEVICE = { "domoticzDevice", "Domoticz Device"};
|
||||
public final static String[] SOMFY_DEVICE = { "somfyDevice", "Somfy Device"};
|
||||
public final static String[] LIFX_DEVICE = { "lifxDevice", "LIFX Device"};
|
||||
public final static String[] OPENHAB_DEVICE = { "openhabDevice", "OpenHAB Device"};
|
||||
public final static String[] FHEM_DEVICE = { "fhemDevice", "FHEM Device"};
|
||||
public final static String[] BROADLINK_DEVICE = { "broadlinkDevice", "Broadlink Device"};
|
||||
|
||||
public final static int typeIndex = 0;
|
||||
public final static int displayIndex = 1;
|
||||
@@ -46,18 +52,23 @@ public class DeviceMapTypes {
|
||||
deviceMapTypes.add(HARMONY_ACTIVITY);
|
||||
deviceMapTypes.add(HARMONY_BUTTON);
|
||||
deviceMapTypes.add(HASS_DEVICE);
|
||||
deviceMapTypes.add(HOMEWIZARD_DEVICE);
|
||||
deviceMapTypes.add(HTTP_DEVICE);
|
||||
deviceMapTypes.add(HUE_DEVICE);
|
||||
deviceMapTypes.add(LIFX_DEVICE);
|
||||
deviceMapTypes.add(MQTT_MESSAGE);
|
||||
deviceMapTypes.add(NEST_HOMEAWAY);
|
||||
deviceMapTypes.add(NEST_THERMO_SET);
|
||||
deviceMapTypes.add(SOMFY_DEVICE);
|
||||
deviceMapTypes.add(TCP_DEVICE);
|
||||
deviceMapTypes.add(UDP_DEVICE);
|
||||
deviceMapTypes.add(VERA_DEVICE);
|
||||
deviceMapTypes.add(VERA_SCENE);
|
||||
deviceMapTypes.add(FIBARO_DEVICE);
|
||||
deviceMapTypes.add(FIBARO_SCENE);
|
||||
deviceMapTypes.add(SOMFY_DEVICE);
|
||||
deviceMapTypes.add(OPENHAB_DEVICE);
|
||||
deviceMapTypes.add(FHEM_DEVICE);
|
||||
deviceMapTypes.add(BROADLINK_DEVICE);
|
||||
}
|
||||
public static int getTypeIndex() {
|
||||
return typeIndex;
|
||||
|
||||
@@ -2,11 +2,14 @@ package com.bwssystems.HABridge;
|
||||
|
||||
import static spark.Spark.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.devicemanagmeent.*;
|
||||
import com.bwssystems.HABridge.hue.HueMulator;
|
||||
import com.bwssystems.HABridge.plugins.http.HttpClientPool;
|
||||
import com.bwssystems.HABridge.upnp.UpnpListener;
|
||||
import com.bwssystems.HABridge.upnp.UpnpSettingsResource;
|
||||
import com.bwssystems.HABridge.util.UDPDatagramSender;
|
||||
@@ -39,21 +42,26 @@ public class HABridge {
|
||||
SystemControl theSystem;
|
||||
BridgeSettings bridgeSettings;
|
||||
Version theVersion;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
HttpClientPool thePool;
|
||||
|
||||
log.info("HA Bridge startup sequence...");
|
||||
theVersion = new Version();
|
||||
// Singleton initialization
|
||||
thePool = new HttpClientPool();
|
||||
|
||||
log.info("HA Bridge (v" + theVersion.getVersion() + ") starting....");
|
||||
|
||||
bridgeSettings = new BridgeSettings();
|
||||
// sparkjava config directive to set html static file location for Jetty
|
||||
staticFileLocation("/public");
|
||||
while(!bridgeSettings.getBridgeControl().isStop()) {
|
||||
bridgeSettings.buildSettings();
|
||||
log.info("HA Bridge initializing....");
|
||||
bridgeSettings.getBridgeSecurity().removeTestUsers();
|
||||
log.info("HA Bridge (v" + theVersion.getVersion() + ") initializing....");
|
||||
// sparkjava config directive to set ip address for the web server to listen on
|
||||
ipAddress(bridgeSettings.getBridgeSettingsDescriptor().getWebaddress());
|
||||
// sparkjava config directive to set port for the web server to listen on
|
||||
port(bridgeSettings.getBridgeSettingsDescriptor().getServerPort());
|
||||
staticFileLocation("/public");
|
||||
initExceptionHandler((e) -> HABridge.theExceptionHandler(e, bridgeSettings.getBridgeSettingsDescriptor().getServerPort()));
|
||||
if(!bridgeSettings.getBridgeControl().isReinit())
|
||||
init();
|
||||
bridgeSettings.getBridgeControl().setReinit(false);
|
||||
@@ -71,23 +79,35 @@ public class HABridge {
|
||||
homeManager.buildHomes(bridgeSettings, udpSender);
|
||||
// setup the class to handle the resource setup rest api
|
||||
theResources = new DeviceResource(bridgeSettings, homeManager);
|
||||
// setup the class to handle the upnp response rest api
|
||||
theSettingResponder = new UpnpSettingsResource(bridgeSettings.getBridgeSettingsDescriptor());
|
||||
theSettingResponder.setupServer();
|
||||
// setup the class to handle the hue emulator rest api
|
||||
theHueMulator = new HueMulator(bridgeSettings, theResources.getDeviceRepository(), homeManager);
|
||||
theHueMulator = new HueMulator(bridgeSettings, theResources.getDeviceRepository(), theResources.getGroupRepository(), homeManager);
|
||||
theHueMulator.setupServer();
|
||||
// wait for the sparkjava initialization of the rest api classes to be complete
|
||||
awaitInitialization();
|
||||
|
||||
|
||||
if(bridgeSettings.getBridgeSettingsDescriptor().isTraceupnp())
|
||||
log.info("Traceupnp: upnp config address: " + bridgeSettings.getBridgeSettingsDescriptor().getUpnpConfigAddress() + "-useIface:" +
|
||||
bridgeSettings.getBridgeSettingsDescriptor().isUseupnpiface() + " on web server: " +
|
||||
bridgeSettings.getBridgeSettingsDescriptor().getWebaddress() + ":" + bridgeSettings.getBridgeSettingsDescriptor().getServerPort());
|
||||
// setup the class to handle the upnp response rest api
|
||||
theSettingResponder = new UpnpSettingsResource(bridgeSettings);
|
||||
theSettingResponder.setupServer();
|
||||
|
||||
// start the upnp ssdp discovery listener
|
||||
theUpnpListener = new UpnpListener(bridgeSettings.getBridgeSettingsDescriptor(), bridgeSettings.getBridgeControl(), udpSender);
|
||||
if(theUpnpListener.startListening())
|
||||
theUpnpListener = null;
|
||||
try {
|
||||
theUpnpListener = new UpnpListener(bridgeSettings.getBridgeSettingsDescriptor(), bridgeSettings.getBridgeControl(), udpSender);
|
||||
} catch (IOException e) {
|
||||
log.error("Could not initialize UpnpListener, exiting....", e);
|
||||
theUpnpListener = null;
|
||||
}
|
||||
if(theUpnpListener != null && theUpnpListener.startListening())
|
||||
log.info("HA Bridge (v" + theVersion.getVersion() + ") reinitialization requessted....");
|
||||
else
|
||||
bridgeSettings.getBridgeControl().setStop(true);
|
||||
if(bridgeSettings.getBridgeSettingsDescriptor().isSettingsChanged())
|
||||
bridgeSettings.save(bridgeSettings.getBridgeSettingsDescriptor());
|
||||
log.info("Going to close all homes");
|
||||
homeManager.closeHomes();
|
||||
udpSender.closeResponseSocket();
|
||||
udpSender = null;
|
||||
@@ -97,12 +117,28 @@ public class HABridge {
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
log.error("Sleep error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
bridgeSettings.getBridgeSecurity().removeTestUsers();
|
||||
if(bridgeSettings.getBridgeSecurity().isSettingsChanged())
|
||||
bridgeSettings.updateConfigFile();
|
||||
try {
|
||||
HttpClientPool.shutdown();
|
||||
} catch (InterruptedException e) {
|
||||
log.warn("Error shutting down http pool: " + e.getMessage());;
|
||||
} catch (IOException e) {
|
||||
log.warn("Error shutting down http pool: " + e.getMessage());;
|
||||
}
|
||||
thePool = null;
|
||||
log.info("HA Bridge (v" + theVersion.getVersion() + ") exiting....");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
private static void theExceptionHandler(Exception e, Integer thePort) {
|
||||
Logger log = LoggerFactory.getLogger(HABridge.class);
|
||||
log.error("Could not start ha-bridge webservice on port [" + thePort + "] due to: " + e.getMessage());
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,24 +4,33 @@ import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.devicemanagmeent.ResourceHandler;
|
||||
import com.bwssystems.HABridge.plugins.NestBridge.NestHome;
|
||||
import com.bwssystems.HABridge.plugins.broadlink.BroadlinkHome;
|
||||
import com.bwssystems.HABridge.plugins.domoticz.DomoticzHome;
|
||||
import com.bwssystems.HABridge.plugins.exec.CommandHome;
|
||||
import com.bwssystems.HABridge.plugins.fhem.FHEMHome;
|
||||
import com.bwssystems.HABridge.plugins.hal.HalHome;
|
||||
import com.bwssystems.HABridge.plugins.harmony.HarmonyHome;
|
||||
import com.bwssystems.HABridge.plugins.hass.HassHome;
|
||||
import com.bwssystems.HABridge.plugins.homewizard.HomeWizardHome;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHome;
|
||||
import com.bwssystems.HABridge.plugins.hue.HueHome;
|
||||
import com.bwssystems.HABridge.plugins.lifx.LifxHome;
|
||||
import com.bwssystems.HABridge.plugins.mqtt.MQTTHome;
|
||||
import com.bwssystems.HABridge.plugins.openhab.OpenHABHome;
|
||||
import com.bwssystems.HABridge.plugins.somfy.SomfyHome;
|
||||
import com.bwssystems.HABridge.plugins.tcp.TCPHome;
|
||||
import com.bwssystems.HABridge.plugins.udp.UDPHome;
|
||||
import com.bwssystems.HABridge.plugins.vera.VeraHome;
|
||||
import com.bwssystems.HABridge.plugins.fibaro.FibaroHome;
|
||||
import com.bwssystems.HABridge.util.UDPDatagramSender;
|
||||
|
||||
public class HomeManager {
|
||||
private static final Logger log = LoggerFactory.getLogger(HomeManager.class);
|
||||
Map<String, Home> homeList;
|
||||
Map<String, Home> resourceList;
|
||||
|
||||
@@ -33,6 +42,14 @@ public class HomeManager {
|
||||
// factory method
|
||||
public void buildHomes(BridgeSettings bridgeSettings, UDPDatagramSender aUdpDatagramSender) {
|
||||
Home aHome = null;
|
||||
//setup the http handler Home - This must be the first home created for devMode
|
||||
aHome = new HTTPHome(bridgeSettings);
|
||||
homeList.put(DeviceMapTypes.HTTP_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.CUSTOM_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.VERA_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.VERA_SCENE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.FIBARO_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.FIBARO_SCENE[DeviceMapTypes.typeIndex], aHome);
|
||||
//setup the harmony connection if available
|
||||
aHome = new HarmonyHome(bridgeSettings);
|
||||
resourceList.put(DeviceMapTypes.HARMONY_ACTIVITY[DeviceMapTypes.typeIndex], aHome);
|
||||
@@ -63,16 +80,14 @@ public class HomeManager {
|
||||
aHome = new HassHome(bridgeSettings);
|
||||
resourceList.put(DeviceMapTypes.HASS_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.HASS_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
// Setup the HomeWizard configuration if available
|
||||
aHome = new HomeWizardHome(bridgeSettings);
|
||||
resourceList.put(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
//setup the command execution Home
|
||||
aHome = new CommandHome(bridgeSettings);
|
||||
homeList.put(DeviceMapTypes.EXEC_DEVICE_COMPAT[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.CMD_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
//setup the http handler Home
|
||||
aHome = new HTTPHome(bridgeSettings);
|
||||
homeList.put(DeviceMapTypes.HTTP_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.CUSTOM_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.VERA_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.VERA_SCENE[DeviceMapTypes.typeIndex], aHome);
|
||||
//setup the tcp handler Home
|
||||
aHome = new TCPHome(bridgeSettings);
|
||||
homeList.put(DeviceMapTypes.TCP_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
@@ -85,11 +100,15 @@ public class HomeManager {
|
||||
aHome = new VeraHome(bridgeSettings);
|
||||
resourceList.put(DeviceMapTypes.VERA_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
resourceList.put(DeviceMapTypes.VERA_SCENE[DeviceMapTypes.typeIndex], aHome);
|
||||
// Setup Fibaro Home if available
|
||||
aHome = new FibaroHome(bridgeSettings);
|
||||
resourceList.put(DeviceMapTypes.FIBARO_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
resourceList.put(DeviceMapTypes.FIBARO_SCENE[DeviceMapTypes.typeIndex], aHome);
|
||||
//setup the Domoticz configuration if available
|
||||
aHome = new DomoticzHome(bridgeSettings);
|
||||
homeList.put(DeviceMapTypes.DOMOTICZ_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
resourceList.put(DeviceMapTypes.DOMOTICZ_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
//setup the Somfy configuration if available
|
||||
//setup the Somfy configuration if availableOPENHAB
|
||||
aHome = new SomfyHome(bridgeSettings);
|
||||
homeList.put(DeviceMapTypes.SOMFY_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
resourceList.put(DeviceMapTypes.SOMFY_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
@@ -97,6 +116,18 @@ public class HomeManager {
|
||||
aHome = new LifxHome(bridgeSettings);
|
||||
resourceList.put(DeviceMapTypes.LIFX_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.LIFX_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
//setup the OpenHAB configuration if available
|
||||
aHome = new OpenHABHome(bridgeSettings);
|
||||
resourceList.put(DeviceMapTypes.OPENHAB_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.OPENHAB_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
//setup the OpenHAB configuration if available
|
||||
aHome = new FHEMHome(bridgeSettings);
|
||||
resourceList.put(DeviceMapTypes.FHEM_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.FHEM_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
//setup the Broadlink configuration if available
|
||||
aHome = new BroadlinkHome(bridgeSettings);
|
||||
resourceList.put(DeviceMapTypes.BROADLINK_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.BROADLINK_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
}
|
||||
|
||||
public Home findHome(String type) {
|
||||
@@ -107,8 +138,10 @@ public class HomeManager {
|
||||
}
|
||||
|
||||
public void closeHomes() {
|
||||
log.info("Manager close homes called....");
|
||||
Collection<Home> theHomes = homeList.values();
|
||||
for(Home aHome : theHomes) {
|
||||
log.info("Closing home: " + aHome.getClass().getCanonicalName());
|
||||
aHome.closeHome();
|
||||
}
|
||||
homeList.clear();
|
||||
|
||||
@@ -10,15 +10,18 @@ public class LinkButtonPressed extends TimerTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(LinkButtonPressed.class);
|
||||
private BridgeControlDescriptor linkDescriptor;
|
||||
private Timer myTimer;
|
||||
private boolean isSilent;
|
||||
|
||||
public LinkButtonPressed(BridgeControlDescriptor theDescriptor, Timer aTimer) {
|
||||
public LinkButtonPressed(BridgeControlDescriptor theDescriptor, Timer aTimer, boolean keepSilent) {
|
||||
linkDescriptor = theDescriptor;
|
||||
myTimer = aTimer;
|
||||
isSilent = keepSilent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
log.info("Link button time ended....");
|
||||
if(!isSilent)
|
||||
log.info("Link button time ended....");
|
||||
linkDescriptor.setLinkButton(false);
|
||||
myTimer.cancel();
|
||||
}
|
||||
|
||||
20
src/main/java/com/bwssystems/HABridge/LinkParams.java
Normal file
20
src/main/java/com/bwssystems/HABridge/LinkParams.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package com.bwssystems.HABridge;
|
||||
|
||||
public class LinkParams {
|
||||
private Integer seconds;
|
||||
private boolean silent;
|
||||
|
||||
public Integer getSeconds() {
|
||||
return seconds;
|
||||
}
|
||||
public void setSeconds(Integer seconds) {
|
||||
this.seconds = seconds;
|
||||
}
|
||||
public boolean isSilent() {
|
||||
return silent;
|
||||
}
|
||||
public void setSilent(boolean silent) {
|
||||
this.silent = silent;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +1,15 @@
|
||||
package com.bwssystems.HABridge;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public class NamedIP {
|
||||
private String name;
|
||||
private String ip;
|
||||
private String webhook;
|
||||
private String ip;
|
||||
private String webhook;
|
||||
private String port;
|
||||
private String username;
|
||||
private String password;
|
||||
private JsonObject extensions;
|
||||
private Boolean secure;
|
||||
|
||||
public String getName() {
|
||||
@@ -51,4 +54,10 @@ public class NamedIP {
|
||||
public void setSecure(Boolean secure) {
|
||||
this.secure = secure;
|
||||
}
|
||||
public JsonObject getExtensions() {
|
||||
return extensions;
|
||||
}
|
||||
public void setExtensions(JsonObject extensions) {
|
||||
this.extensions = extensions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.bwssystems.HABridge;
|
||||
|
||||
public class SecurityInfo {
|
||||
private boolean useLinkButton;
|
||||
private String execGarden;
|
||||
private boolean secureHueApi;
|
||||
private boolean isSecure;
|
||||
|
||||
@@ -12,12 +11,6 @@ public class SecurityInfo {
|
||||
public void setUseLinkButton(boolean useLinkButton) {
|
||||
this.useLinkButton = useLinkButton;
|
||||
}
|
||||
public String getExecGarden() {
|
||||
return execGarden;
|
||||
}
|
||||
public void setExecGarden(String execGarden) {
|
||||
this.execGarden = execGarden;
|
||||
}
|
||||
public boolean isSecureHueApi() {
|
||||
return secureHueApi;
|
||||
}
|
||||
|
||||
@@ -8,19 +8,26 @@ import static spark.Spark.before;
|
||||
import static spark.Spark.halt;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
//import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Timer;
|
||||
import java.util.Base64;
|
||||
//import java.util.Iterator;
|
||||
//import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
//import com.bwssystems.HABridge.api.NameValue;
|
||||
import com.bwssystems.HABridge.api.hue.WhitelistEntry;
|
||||
import com.bwssystems.HABridge.dao.BackupFilename;
|
||||
import com.bwssystems.HABridge.util.JsonTransformer;
|
||||
import com.bwssystems.HABridge.util.TextStringFormatter;
|
||||
@@ -28,10 +35,12 @@ import com.bwssystems.logservices.LoggerInfo;
|
||||
import com.bwssystems.logservices.LoggingForm;
|
||||
import com.bwssystems.logservices.LoggingManager;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.classic.spi.LoggingEvent;
|
||||
//import ch.qos.logback.core.Appender;
|
||||
import ch.qos.logback.core.read.CyclicBufferAppender;
|
||||
|
||||
public class SystemControl {
|
||||
@@ -51,7 +60,7 @@ public class SystemControl {
|
||||
this.version = theVersion;
|
||||
this.lc = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||
this.dateFormat = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss.SSS");
|
||||
reacquireCBA();
|
||||
setupLoggerSettings();
|
||||
theLogServiceMgr = new LoggingManager();
|
||||
theLogServiceMgr.init();
|
||||
}
|
||||
@@ -78,21 +87,13 @@ public class SystemControl {
|
||||
return "{\"version\":\"" + version.getVersion() + "\",\"isSecure\":" + bridgeSettings.getBridgeSecurity().isSecure() + "}";
|
||||
});
|
||||
|
||||
// http://ip_address:port/system/habridge/testuser gets the valid test user for calling the api
|
||||
get (SYSTEM_CONTEXT + "/habridge/testuser", (request, response) -> {
|
||||
log.debug("Get HA Bridge testuser: " + bridgeSettings.getBridgeSettingsDescriptor().getInternalTestUser());
|
||||
response.status(HttpStatus.SC_OK);
|
||||
response.type("application/json");
|
||||
return "{\"user\":\"" + bridgeSettings.getBridgeSettingsDescriptor().getInternalTestUser() + "\"}";
|
||||
});
|
||||
|
||||
// http://ip_address:port/system/logmsgs gets the log messages for the bridge
|
||||
get (SYSTEM_CONTEXT + "/logmsgs", (request, response) -> {
|
||||
log.debug("Get logmsgs.");
|
||||
String logMsgs;
|
||||
int count = -1;
|
||||
if(cyclicBufferAppender == null)
|
||||
reacquireCBA();
|
||||
setupLoggerSettings();
|
||||
if (cyclicBufferAppender != null) {
|
||||
count = cyclicBufferAppender.getLength();
|
||||
}
|
||||
@@ -253,10 +254,22 @@ public class SystemControl {
|
||||
});
|
||||
// http://ip_address:port/system/presslinkbutton which sets the link button for device registration
|
||||
put(SYSTEM_CONTEXT + "/presslinkbutton", (request, response) -> {
|
||||
log.info("Link button pressed....");
|
||||
LinkParams linkParams = null;
|
||||
if(!request.body().isEmpty()) {
|
||||
linkParams = new Gson().fromJson(request.body(), LinkParams.class);
|
||||
if(linkParams.getSeconds() <= 0)
|
||||
linkParams.setSeconds(1);
|
||||
}
|
||||
else {
|
||||
linkParams = new LinkParams();
|
||||
linkParams.setSilent(false);
|
||||
linkParams.setSeconds(30);
|
||||
}
|
||||
if(!linkParams.isSilent())
|
||||
log.info("Link button pressed....");
|
||||
bridgeSettings.getBridgeControl().setLinkButton(true);
|
||||
Timer theTimer = new Timer();
|
||||
theTimer.schedule(new LinkButtonPressed(bridgeSettings.getBridgeControl(), theTimer), 30000);
|
||||
theTimer.schedule(new LinkButtonPressed(bridgeSettings.getBridgeControl(), theTimer, linkParams.isSilent()), (linkParams.getSeconds() * 1000));
|
||||
response.status(HttpStatus.SC_OK);
|
||||
response.type("application/json");
|
||||
return "";
|
||||
@@ -283,8 +296,6 @@ public class SystemControl {
|
||||
post(SYSTEM_CONTEXT + "/changesecurityinfo", (request, response) -> {
|
||||
log.debug("changesecurityinfo....");
|
||||
SecurityInfo theInfo = new Gson().fromJson(request.body(), SecurityInfo.class);
|
||||
if(theInfo.getExecGarden() != null)
|
||||
bridgeSettings.getBridgeSecurity().setExecGarden(theInfo.getExecGarden());
|
||||
bridgeSettings.getBridgeSecurity().setUseLinkButton(theInfo.isUseLinkButton());
|
||||
bridgeSettings.getBridgeSecurity().setSecureHueApi(theInfo.isSecureHueApi());
|
||||
bridgeSettings.save(bridgeSettings.getBridgeSettingsDescriptor());
|
||||
@@ -293,6 +304,36 @@ public class SystemControl {
|
||||
return bridgeSettings.getBridgeSecurity().getSecurityInfo();
|
||||
}, new JsonTransformer());
|
||||
|
||||
// http://ip_address:port/system/whitelist gets the whitelist for the bridge
|
||||
get (SYSTEM_CONTEXT + "/whitelist", (request, response) -> {
|
||||
log.debug("Get whitelist");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
response.type("application/json");
|
||||
return bridgeSettings.getBridgeSecurity().getWhitelist();
|
||||
}, new JsonTransformer());
|
||||
|
||||
// http://ip_address:port/system/setwhitelist CORS request
|
||||
options(SYSTEM_CONTEXT + "/setwhitelist", (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/system/setwhitelist which sets the whitelist after being managed
|
||||
post(SYSTEM_CONTEXT + "/setwhitelist", (request, response) -> {
|
||||
log.debug("setwhitelist....");
|
||||
Type listType = new TypeToken<Map<String, WhitelistEntry>>() {
|
||||
}.getType();
|
||||
Map<String, WhitelistEntry> aWhitelist = new Gson().fromJson(request.body(), listType);
|
||||
bridgeSettings.getBridgeSecurity().setWhitelist(aWhitelist);
|
||||
bridgeSettings.save(bridgeSettings.getBridgeSettingsDescriptor());
|
||||
response.status(HttpStatus.SC_OK);
|
||||
response.type("application/json");
|
||||
return bridgeSettings.getBridgeSecurity().getWhitelist();
|
||||
}, new JsonTransformer());
|
||||
|
||||
// http://ip_address:port/system/logmgmt/update CORS request
|
||||
options(SYSTEM_CONTEXT + "/logmgmt/update", (request, response) -> {
|
||||
response.status(HttpStatus.SC_OK);
|
||||
@@ -320,6 +361,8 @@ public class SystemControl {
|
||||
log.debug("bridge settings requested from " + request.ip());
|
||||
response.status(HttpStatus.SC_OK);
|
||||
response.type("application/json");
|
||||
// if(bridgeSettings.getBridgeSettingsDescriptor().getActiveloggers() == null)
|
||||
// bridgeSettings.getBridgeSettingsDescriptor().setActiveloggers(getLogAppenders());
|
||||
return bridgeSettings.getBridgeSettingsDescriptor();
|
||||
}, new JsonTransformer());
|
||||
|
||||
@@ -336,6 +379,8 @@ public class SystemControl {
|
||||
put(SYSTEM_CONTEXT + "/settings", (request, response) -> {
|
||||
log.debug("save bridge settings requested from " + request.ip() + " with body: " + request.body());
|
||||
BridgeSettingsDescriptor newBridgeSettings = new Gson().fromJson(request.body(), BridgeSettingsDescriptor.class);
|
||||
if(newBridgeSettings.getUpnpsenddelay() > 15000)
|
||||
newBridgeSettings.setUpnpsenddelay(15000);
|
||||
bridgeSettings.save(newBridgeSettings);
|
||||
response.status(HttpStatus.SC_OK);
|
||||
response.type("application/json");
|
||||
@@ -446,11 +491,42 @@ public class SystemControl {
|
||||
}, new JsonTransformer());
|
||||
}
|
||||
|
||||
void reacquireCBA() {
|
||||
cyclicBufferAppender = (CyclicBufferAppender<ILoggingEvent>) lc.getLogger(
|
||||
private void setupLoggerSettings() {
|
||||
// final ch.qos.logback.classic.Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||
|
||||
cyclicBufferAppender = (CyclicBufferAppender<ILoggingEvent>) lc.getLogger(
|
||||
Logger.ROOT_LOGGER_NAME).getAppender(CYCLIC_BUFFER_APPENDER_NAME);
|
||||
cyclicBufferAppender.setMaxSize(bridgeSettings.getBridgeSettingsDescriptor().getNumberoflogmessages());
|
||||
}
|
||||
// if(bridgeSettings.getBridgeSettingsDescriptor().getActiveloggers() != null) {
|
||||
// for (NameValue temp : bridgeSettings.getBridgeSettingsDescriptor().getActiveloggers()) {
|
||||
// if(temp.getValue().equals("false"))
|
||||
// logger.detachAppender(temp.getName());
|
||||
// }
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
||||
// private List<NameValue> getLogAppenders() {
|
||||
// final ch.qos.logback.classic.Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||
//
|
||||
// final Iterator<Appender<ILoggingEvent>> it = logger.iteratorForAppenders();
|
||||
//
|
||||
// List<NameValue> theLoggers = new ArrayList<NameValue>();
|
||||
//
|
||||
// while (it.hasNext()) {
|
||||
//
|
||||
// final Appender<ILoggingEvent> appender = it.next();
|
||||
//
|
||||
// if (!(appender instanceof CyclicBufferAppender)) {
|
||||
// NameValue theLogger = new NameValue();
|
||||
// theLogger.setName(appender.getName());
|
||||
// theLogger.setValue("true");
|
||||
// theLoggers.add(theLogger);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return theLoggers;
|
||||
// }
|
||||
|
||||
protected void pingListener() {
|
||||
try {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.bwssystems.HABridge.api.hue;
|
||||
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.dao.GroupDescriptor;
|
||||
|
||||
/**
|
||||
* Created by arm on 4/14/15.
|
||||
@@ -14,6 +15,8 @@ public class DeviceResponse {
|
||||
private String luminaireuniqueid;
|
||||
private String uniqueid;
|
||||
private String swversion;
|
||||
private String swconfigid;
|
||||
private String productid;
|
||||
|
||||
public DeviceState getState() {
|
||||
return state;
|
||||
@@ -71,6 +74,23 @@ public class DeviceResponse {
|
||||
this.swversion = swversion;
|
||||
}
|
||||
|
||||
public String getSwconfigid() {
|
||||
return swconfigid;
|
||||
}
|
||||
|
||||
public void setSwconfigid(String swconfigid) {
|
||||
this.swconfigid = swconfigid;
|
||||
}
|
||||
|
||||
public String getProductid() {
|
||||
return productid;
|
||||
}
|
||||
|
||||
public void setProductid(String productid) {
|
||||
this.productid = productid;
|
||||
}
|
||||
|
||||
|
||||
public String getLuminaireuniqueid() {
|
||||
return luminaireuniqueid;
|
||||
}
|
||||
@@ -86,11 +106,41 @@ public class DeviceResponse {
|
||||
response.setName(device.getName());
|
||||
response.setUniqueid(device.getUniqueid());
|
||||
response.setManufacturername("Philips");
|
||||
response.setType("Dimmable light");
|
||||
response.setModelid("LWB004");
|
||||
response.setSwversion("66012040");
|
||||
|
||||
if (device.isColorDevice()) {
|
||||
response.setType("Extended color light");
|
||||
response.setModelid("LCT010");
|
||||
response.setSwversion("1.15.2_r19181");
|
||||
response.setSwconfigid("F921C859");
|
||||
response.setProductid("Philips-LCT010-1-A19ECLv4");
|
||||
} else {
|
||||
response.setType("Dimmable light");
|
||||
response.setModelid("LWB007");
|
||||
response.setSwversion("66012040");
|
||||
}
|
||||
|
||||
response.setLuminaireuniqueid(null);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public static DeviceResponse createResponseForVirtualLight(GroupDescriptor group){
|
||||
DeviceResponse response = new DeviceResponse();
|
||||
response.setState(group.getAction());
|
||||
|
||||
response.setName(group.getName());
|
||||
response.setUniqueid("00:17:88:5E:D3:FF-" + String.format("%02X", Integer.parseInt(group.getId())));
|
||||
response.setManufacturername("Philips");
|
||||
response.setType("Extended color light");
|
||||
response.setModelid("LCT010");
|
||||
response.setSwversion("1.15.2_r19181");
|
||||
response.setSwconfigid("F921C859");
|
||||
response.setProductid("Philips-LCT010-1-A19ECLv4");
|
||||
|
||||
response.setLuminaireuniqueid(null);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.bwssystems.HABridge.api.hue;
|
||||
|
||||
// import java.util.ArrayList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -9,14 +9,15 @@ import java.util.List;
|
||||
public class DeviceState {
|
||||
private boolean on;
|
||||
private int bri;
|
||||
private int hue;
|
||||
private int sat;
|
||||
private Integer hue;
|
||||
private Integer sat;
|
||||
private String effect;
|
||||
private int ct;
|
||||
private List<Double> xy;
|
||||
private Integer ct;
|
||||
private String alert;
|
||||
private String colormode;
|
||||
private boolean reachable;
|
||||
private List<Double> xy;
|
||||
|
||||
// private int transitiontime;
|
||||
|
||||
public boolean isOn() {
|
||||
@@ -36,19 +37,21 @@ public class DeviceState {
|
||||
}
|
||||
|
||||
public int getHue() {
|
||||
return hue;
|
||||
return hue != null ? hue.intValue() : 0;
|
||||
}
|
||||
|
||||
public void setHue(int hue) {
|
||||
this.hue = hue;
|
||||
this.colormode = "hs";
|
||||
}
|
||||
|
||||
public int getSat() {
|
||||
return sat;
|
||||
return sat != null ? sat.intValue() : 0;
|
||||
}
|
||||
|
||||
public void setSat(int sat) {
|
||||
this.sat = sat;
|
||||
this.colormode = "hs";
|
||||
}
|
||||
|
||||
public String getEffect() {
|
||||
@@ -60,11 +63,12 @@ public class DeviceState {
|
||||
}
|
||||
|
||||
public int getCt() {
|
||||
return ct;
|
||||
return ct != null ? ct.intValue() : 0;
|
||||
}
|
||||
|
||||
public void setCt(int ct) {
|
||||
this.ct = ct;
|
||||
this.colormode = "ct";
|
||||
}
|
||||
|
||||
public String getAlert() {
|
||||
@@ -97,6 +101,7 @@ public class DeviceState {
|
||||
|
||||
public void setXy(List<Double> xy) {
|
||||
this.xy = xy;
|
||||
this.colormode = "xy";
|
||||
}
|
||||
// public int getTransitiontime() {
|
||||
// return transitiontime;
|
||||
@@ -106,22 +111,28 @@ public class DeviceState {
|
||||
// this.transitiontime = transitiontime;
|
||||
// }
|
||||
|
||||
public static DeviceState createDeviceState() {
|
||||
public static DeviceState createDeviceState(boolean color) {
|
||||
DeviceState newDeviceState = new DeviceState();
|
||||
newDeviceState.fillIn();
|
||||
// newDeviceState.setColormode("none");
|
||||
// ArrayList<Double> doubleArray = new ArrayList<Double>();
|
||||
// doubleArray.add(new Double(0));
|
||||
// doubleArray.add(new Double(0));
|
||||
// newDeviceState.setXy(doubleArray);
|
||||
|
||||
newDeviceState.fillIn(color);
|
||||
if (color) {
|
||||
newDeviceState.setColormode("xy");
|
||||
newDeviceState.setHue(0);
|
||||
newDeviceState.setSat(0);
|
||||
newDeviceState.setCt(153);
|
||||
ArrayList<Double> doubleArray = new ArrayList<Double>();
|
||||
doubleArray.add(0.3146);
|
||||
doubleArray.add(0.3303);
|
||||
newDeviceState.setXy(doubleArray);
|
||||
}
|
||||
return newDeviceState;
|
||||
}
|
||||
public void fillIn() {
|
||||
public void fillIn(boolean color) {
|
||||
if(this.getAlert() == null)
|
||||
this.setAlert("none");
|
||||
if(this.getEffect() == null)
|
||||
this.setEffect("none");
|
||||
if (color) {
|
||||
if(this.getEffect() == null)
|
||||
this.setEffect("none");
|
||||
}
|
||||
this.setReachable(true);
|
||||
}
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.bwssystems.HABridge.api.hue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class GroupClassTypes {
|
||||
|
||||
public final static String BATHROOM = "Bathroom";
|
||||
public final static String BEDROOM = "Bedroom";
|
||||
public final static String CARPORT = "Carport";
|
||||
public final static String DINING = "Dining";
|
||||
public final static String DRIVEWAY = "Driveway";
|
||||
public final static String FRONT_DOOR = "Front door";
|
||||
public final static String GARAGE = "Garage";
|
||||
public final static String GARDEN = "Garden";
|
||||
public final static String GYM = "Gym";
|
||||
public final static String HALLWAY = "Hallway";
|
||||
public final static String BEDROOM_KIDS = "Kids bedroom";
|
||||
public final static String KITCHEN = "Kitchen";
|
||||
public final static String LIVING_ROOM = "Living room";
|
||||
public final static String NURSERY = "Nursery";
|
||||
public final static String OFFICE = "Office";
|
||||
public final static String OTHER = "Other";
|
||||
public final static String RECREATION = "Recreation";
|
||||
public final static String TERRACE = "Terrace";
|
||||
public final static String TOILET = "Toilet";
|
||||
|
||||
ArrayList<String> groupClassTypes;
|
||||
|
||||
public GroupClassTypes() {
|
||||
groupClassTypes = new ArrayList<String>();
|
||||
groupClassTypes.add(BATHROOM);
|
||||
groupClassTypes.add(BEDROOM);
|
||||
groupClassTypes.add(CARPORT);
|
||||
groupClassTypes.add(DINING);
|
||||
groupClassTypes.add(DRIVEWAY);
|
||||
groupClassTypes.add(FRONT_DOOR);
|
||||
groupClassTypes.add(GARAGE);
|
||||
groupClassTypes.add(GARDEN);
|
||||
groupClassTypes.add(GYM);
|
||||
groupClassTypes.add(HALLWAY);
|
||||
groupClassTypes.add(BEDROOM_KIDS);
|
||||
groupClassTypes.add(KITCHEN);
|
||||
groupClassTypes.add(LIVING_ROOM);
|
||||
groupClassTypes.add(NURSERY);
|
||||
groupClassTypes.add(OFFICE);
|
||||
groupClassTypes.add(OTHER);
|
||||
groupClassTypes.add(RECREATION);
|
||||
groupClassTypes.add(TERRACE);
|
||||
groupClassTypes.add(TOILET);
|
||||
}
|
||||
|
||||
public Boolean validateType(String type) {
|
||||
if(type == null || type.trim().isEmpty())
|
||||
return false;
|
||||
for(String classType : groupClassTypes) {
|
||||
if(type.trim().contentEquals(classType))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.bwssystems.HABridge.api.hue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.dao.GroupDescriptor;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class GroupResponse {
|
||||
@@ -16,6 +16,8 @@ public class GroupResponse {
|
||||
private String type;
|
||||
@SerializedName("class")
|
||||
String class_name;
|
||||
@SerializedName("state")
|
||||
private GroupState state;
|
||||
|
||||
public DeviceState getAction() {
|
||||
return action;
|
||||
@@ -23,6 +25,14 @@ public class GroupResponse {
|
||||
public void setAction(DeviceState action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public GroupState getState() {
|
||||
return state;
|
||||
}
|
||||
public void setState(GroupState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public String[] getLights() {
|
||||
return lights;
|
||||
}
|
||||
@@ -48,34 +58,69 @@ public class GroupResponse {
|
||||
public void setClass_name(String class_name) {
|
||||
this.class_name = class_name;
|
||||
}
|
||||
public static GroupResponse createDefaultGroupResponse(List<DeviceDescriptor> deviceList) {
|
||||
String[] theList = new String[deviceList.size()];
|
||||
int i = 0;
|
||||
for (DeviceDescriptor device : deviceList) {
|
||||
theList[i] = device.getId();
|
||||
i++;
|
||||
}
|
||||
GroupResponse theResponse = new GroupResponse();
|
||||
theResponse.setAction(DeviceState.createDeviceState());
|
||||
theResponse.setName("Lightset 0");
|
||||
theResponse.setLights(theList);
|
||||
theResponse.setType("LightGroup");
|
||||
return theResponse;
|
||||
}
|
||||
public static GroupResponse createOtherGroupResponse(List<DeviceDescriptor> deviceList) {
|
||||
String[] theList = new String[deviceList.size()];
|
||||
int i = 0;
|
||||
for (DeviceDescriptor device : deviceList) {
|
||||
theList[i] = device.getId();
|
||||
i++;
|
||||
}
|
||||
GroupResponse theResponse = new GroupResponse();
|
||||
theResponse.setAction(DeviceState.createDeviceState());
|
||||
theResponse.setName("AGroup");
|
||||
theResponse.setLights(theList);
|
||||
theResponse.setType("Room");
|
||||
theResponse.setClass_name("Other");
|
||||
|
||||
public static GroupResponse createDefaultGroupResponse(Map<String, DeviceResponse> deviceList) {
|
||||
String[] theList = new String[deviceList.size()];
|
||||
Boolean all_on = true;
|
||||
Boolean any_on = false;
|
||||
int i = 0;
|
||||
for (Map.Entry<String, DeviceResponse> device : deviceList.entrySet()) {
|
||||
if (Integer.parseInt(device.getKey()) >= 10000) { // don't show fake lights for other groups
|
||||
continue;
|
||||
}
|
||||
theList[i] = device.getKey();
|
||||
Boolean is_on = device.getValue().getState().isOn();
|
||||
if (is_on)
|
||||
any_on = true;
|
||||
else
|
||||
all_on = false;
|
||||
i++;
|
||||
}
|
||||
GroupResponse theResponse = new GroupResponse();
|
||||
theResponse.setAction(DeviceState.createDeviceState(true));
|
||||
theResponse.setState(new GroupState(all_on, any_on));
|
||||
theResponse.setName("Group 0");
|
||||
theResponse.setLights(theList);
|
||||
theResponse.setType("LightGroup");
|
||||
return theResponse;
|
||||
}
|
||||
|
||||
return theResponse;
|
||||
}
|
||||
public static GroupResponse createResponse(GroupDescriptor group, Map<String, DeviceResponse> lights){
|
||||
GroupResponse response = new GroupResponse();
|
||||
Boolean all_on = true;
|
||||
Boolean any_on = false;
|
||||
String[] groupLights = null;
|
||||
if (lights == null) {
|
||||
all_on = false;
|
||||
groupLights = group.getLights();
|
||||
} else {
|
||||
for (DeviceResponse light : lights.values()) {
|
||||
Boolean is_on = light.getState().isOn();
|
||||
if (is_on)
|
||||
any_on = true;
|
||||
else
|
||||
all_on = false;
|
||||
}
|
||||
|
||||
// group.getLights() is not filtered by requester, lights is
|
||||
// we want the filtered version but keep the order from group.getLights()
|
||||
groupLights = new String[lights.size()];
|
||||
int i = 0;
|
||||
for (String light : group.getLights()) {
|
||||
if (lights.keySet().contains(light)) {
|
||||
groupLights[i] = light;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response.setState(new GroupState(all_on, any_on));
|
||||
response.setAction(group.getAction());
|
||||
response.setName(group.getName());
|
||||
response.setType(group.getGroupType());
|
||||
response.setLights(groupLights);
|
||||
response.setClass_name(group.getGroupClass());
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.bwssystems.HABridge.api.hue;
|
||||
|
||||
/**
|
||||
* Created by Florian Foerderreuther on 07/23/17
|
||||
*/
|
||||
public class GroupState {
|
||||
private boolean all_on;
|
||||
private boolean any_on;
|
||||
|
||||
public boolean isAllOn() {
|
||||
return all_on;
|
||||
}
|
||||
|
||||
public boolean isAnyOn() {
|
||||
return any_on;
|
||||
}
|
||||
|
||||
public void setState(boolean all_on, boolean any_on) {
|
||||
this.all_on = all_on;
|
||||
this.any_on = any_on;
|
||||
}
|
||||
|
||||
public GroupState(boolean all_on, boolean any_on) {
|
||||
this.all_on = all_on;
|
||||
this.any_on = any_on;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GroupState{" +
|
||||
"all_on=" + all_on +
|
||||
", any_on=" + any_on +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -18,9 +18,9 @@ public class HueApiResponse {
|
||||
private Map<String, JsonObject> rules;
|
||||
private HueConfig config;
|
||||
|
||||
public HueApiResponse(String name, String ipaddress, Map<String, WhitelistEntry> awhitelist, String emulateHubVersion) {
|
||||
public HueApiResponse(String name, String ipaddress, Map<String, WhitelistEntry> awhitelist, String emulateHubVersion, boolean isLinkButtonPressed, String emulateMAC) {
|
||||
super();
|
||||
this.setConfig(HueConfig.createConfig(name, ipaddress, awhitelist, emulateHubVersion));
|
||||
this.setConfig(HueConfig.createConfig(name, ipaddress, awhitelist, emulateHubVersion, isLinkButtonPressed, emulateMAC));
|
||||
this.setRules(new HashMap<>());
|
||||
this.setSensors(new HashMap<>());
|
||||
this.setSchedules(new HashMap<>());
|
||||
|
||||
@@ -34,7 +34,7 @@ public class HueConfig
|
||||
private String replacesbridgeid;
|
||||
private Map<String, WhitelistEntry> whitelist;
|
||||
|
||||
public static HueConfig createConfig(String name, String ipaddress, Map<String, WhitelistEntry> awhitelist, String emulateHubVersion) {
|
||||
public static HueConfig createConfig(String name, String ipaddress, Map<String, WhitelistEntry> awhitelist, String emulateHubVersion, boolean isLinkButtonPressed, String emulateMAC) {
|
||||
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");
|
||||
@@ -44,7 +44,7 @@ public class HueConfig
|
||||
aConfig.setPortalservices(false);
|
||||
aConfig.setGateway(ipaddress);
|
||||
aConfig.setSwversion(emulateHubVersion);
|
||||
aConfig.setLinkbutton(true);
|
||||
aConfig.setLinkbutton(isLinkButtonPressed);
|
||||
aConfig.setIpaddress(ipaddress);
|
||||
aConfig.setProxyport(0);
|
||||
aConfig.setSwupdate(Swupdate.createSwupdate());
|
||||
@@ -56,7 +56,7 @@ public class HueConfig
|
||||
aConfig.setLocaltime(dateFormat.format(new Date()));
|
||||
aConfig.setTimezone(TimeZone.getDefault().getID());
|
||||
aConfig.setZigbeechannel("6");
|
||||
aConfig.setBridgeid(HuePublicConfig.createConfig(name, ipaddress, emulateHubVersion).getHueBridgeIdFromMac());
|
||||
aConfig.setBridgeid(HuePublicConfig.createConfig(name, ipaddress, emulateHubVersion, emulateMAC).getHueBridgeIdFromMac());
|
||||
aConfig.setModelid(HueConstants.MODEL_ID);
|
||||
aConfig.setFactorynew(false);
|
||||
aConfig.setReplacesbridgeid(null);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.bwssystems.HABridge.api.hue;
|
||||
|
||||
public class HueConstants {
|
||||
public final static String HUB_VERSION = "01036659";
|
||||
public final static String API_VERSION = "1.15.0";
|
||||
public final static String HUB_VERSION = "9999999999";
|
||||
public final static String API_VERSION = "1.19.0";
|
||||
public final static String MODEL_ID = "BSB002";
|
||||
public final static String UUID_PREFIX = "2f402f80-da50-11e1-9b23-";
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@ public class HuePublicConfig
|
||||
private Boolean factorynew;
|
||||
private String modelid;
|
||||
|
||||
public static HuePublicConfig createConfig(String name, String ipaddress, String emulateHubVersion) {
|
||||
public static HuePublicConfig createConfig(String name, String ipaddress, String emulateHubVersion, String emulateMAC) {
|
||||
HuePublicConfig aConfig = new HuePublicConfig();
|
||||
aConfig.setMac(HuePublicConfig.getMacAddress(ipaddress));
|
||||
aConfig.setMac(HuePublicConfig.getMacAddress(ipaddress, emulateMAC));
|
||||
aConfig.setApiversion(HueConstants.API_VERSION);
|
||||
aConfig.setSwversion(emulateHubVersion);
|
||||
aConfig.setName(name);
|
||||
@@ -32,34 +32,39 @@ public class HuePublicConfig
|
||||
return aConfig;
|
||||
}
|
||||
|
||||
private static String getMacAddress(String addr)
|
||||
private static String getMacAddress(String addr, String aMAC)
|
||||
{
|
||||
InetAddress ip;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
try {
|
||||
if(aMAC == null || aMAC.trim().length() <= 0) {
|
||||
try {
|
||||
|
||||
ip = InetAddress.getByName(addr);
|
||||
|
||||
ip = InetAddress.getByName(addr);
|
||||
|
||||
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
|
||||
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) {
|
||||
|
||||
byte[] mac = network.getHardwareAddress();
|
||||
sb.append("00:00:88:00:bb:ee");
|
||||
|
||||
} catch (SocketException e){
|
||||
|
||||
sb.append("00:00:88:00:bb:ee");
|
||||
|
||||
} catch (Exception e){
|
||||
|
||||
sb.append("00:00:88:00:bb:ee");
|
||||
|
||||
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");
|
||||
|
||||
} catch (Exception e){
|
||||
|
||||
sb.append("00:00:88:00:bb:ee");
|
||||
|
||||
}
|
||||
else {
|
||||
sb.append(aMAC.trim());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
|
||||
@@ -38,6 +38,9 @@ public class DeviceDescriptor{
|
||||
@SerializedName("onUrl")
|
||||
@Expose
|
||||
private String onUrl;
|
||||
@SerializedName("colorUrl")
|
||||
@Expose
|
||||
private String colorUrl;
|
||||
@SerializedName("headers")
|
||||
@Expose
|
||||
private String headers;
|
||||
@@ -74,9 +77,16 @@ public class DeviceDescriptor{
|
||||
@SerializedName("comments")
|
||||
@Expose
|
||||
private String comments;
|
||||
|
||||
@SerializedName("deviceState")
|
||||
@Expose
|
||||
private DeviceState deviceState;
|
||||
|
||||
@SerializedName("onFirstDim")
|
||||
@Expose
|
||||
private boolean onFirstDim;
|
||||
@SerializedName("onWhenDimPresent")
|
||||
@Expose
|
||||
private boolean onWhenDimPresent;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -141,6 +151,14 @@ public class DeviceDescriptor{
|
||||
this.onUrl = onUrl;
|
||||
}
|
||||
|
||||
public String getColorUrl() {
|
||||
return colorUrl;
|
||||
}
|
||||
|
||||
public void setColorUrl(String colorUrl) {
|
||||
this.colorUrl = colorUrl;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
@@ -207,7 +225,7 @@ public class DeviceDescriptor{
|
||||
|
||||
public DeviceState getDeviceState() {
|
||||
if(deviceState == null)
|
||||
deviceState = DeviceState.createDeviceState();
|
||||
deviceState = DeviceState.createDeviceState(this.isColorDevice());
|
||||
return deviceState;
|
||||
}
|
||||
|
||||
@@ -263,6 +281,22 @@ public class DeviceDescriptor{
|
||||
this.comments = comments;
|
||||
}
|
||||
|
||||
public boolean isOnFirstDim() {
|
||||
return onFirstDim;
|
||||
}
|
||||
|
||||
public void setOnFirstDim(boolean onFirstDim) {
|
||||
this.onFirstDim = onFirstDim;
|
||||
}
|
||||
|
||||
public boolean isOnWhenDimPresent() {
|
||||
return onWhenDimPresent;
|
||||
}
|
||||
|
||||
public void setOnWhenDimPresent(boolean onWhenDimPresent) {
|
||||
this.onWhenDimPresent = onWhenDimPresent;
|
||||
}
|
||||
|
||||
public boolean containsType(String aType) {
|
||||
if(aType == null)
|
||||
return false;
|
||||
@@ -281,7 +315,22 @@ public class DeviceDescriptor{
|
||||
|
||||
if(this.offUrl != null && this.offUrl.contains(aType))
|
||||
return true;
|
||||
|
||||
if(this.colorUrl != null && this.colorUrl.contains(aType))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isColorDevice() {
|
||||
boolean color = true;
|
||||
if ((deviceType == null || !deviceType.trim().equals("passthru")) && (colorUrl == null || colorUrl.trim().equals(""))) {
|
||||
color = false;
|
||||
} else if (deviceType != null && deviceType.trim().equals("passthru")) {
|
||||
if (deviceState != null && (deviceState.getColormode() == null || deviceState.getColormode().equals(""))) {
|
||||
color = false;
|
||||
}
|
||||
}
|
||||
return color;
|
||||
}
|
||||
}
|
||||
@@ -18,13 +18,21 @@ import javax.xml.bind.DatatypeConverter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.DeviceMapTypes;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.plugins.hue.HueHome;
|
||||
import com.bwssystems.HABridge.util.BackupHandler;
|
||||
import com.bwssystems.HABridge.util.JsonTransformer;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
/*
|
||||
* This is an in memory list to manage the configured devices and saves the list as a JSON string to a file for later
|
||||
* loading.
|
||||
@@ -61,6 +69,7 @@ public class DeviceRepository extends BackupHandler {
|
||||
{
|
||||
DeviceDescriptor list[] = gson.fromJson(jsonContent, DeviceDescriptor[].class);
|
||||
for(int i = 0; i < list.length; i++) {
|
||||
list[i].setDeviceState(null);
|
||||
put(list[i].getId(), list[i]);
|
||||
if(Integer.decode(list[i].getId()) > nextId) {
|
||||
nextId = Integer.decode(list[i].getId());
|
||||
@@ -85,6 +94,10 @@ public class DeviceRepository extends BackupHandler {
|
||||
|
||||
public List<DeviceDescriptor> findAllByRequester(String anAddress) {
|
||||
List<DeviceDescriptor> list = new ArrayList<DeviceDescriptor>(devices.values());
|
||||
return findAllByRequester(anAddress, list);
|
||||
}
|
||||
|
||||
private List<DeviceDescriptor> findAllByRequester(String anAddress, Collection<DeviceDescriptor> list) {
|
||||
List<DeviceDescriptor> theReturnList = new ArrayList<DeviceDescriptor>();
|
||||
Iterator<DeviceDescriptor> anIterator = list.iterator();
|
||||
DeviceDescriptor theDevice;
|
||||
@@ -110,6 +123,45 @@ public class DeviceRepository extends BackupHandler {
|
||||
return theReturnList;
|
||||
}
|
||||
|
||||
public Map<String, DeviceResponse> findAllByGroupWithState(String[] lightsInGroup, String anAddress, HueHome myHueHome, Gson aGsonBuilder) {
|
||||
return findAllByGroupWithState(lightsInGroup, anAddress, myHueHome, aGsonBuilder, false);
|
||||
}
|
||||
|
||||
public Map<String, DeviceResponse> findAllByGroupWithState(String[] lightsInGroup, String anAddress, HueHome myHueHome, Gson aGsonBuilder, boolean ignoreAddress) {
|
||||
Map<String, DeviceResponse> deviceResponseMap = new HashMap<String, DeviceResponse>();
|
||||
Map<String, DeviceDescriptor> lights = new HashMap<String, DeviceDescriptor>(devices);
|
||||
lights.keySet().retainAll(Arrays.asList(lightsInGroup));
|
||||
for (DeviceDescriptor light : (ignoreAddress ? lights.values() : findAllByRequester(anAddress, lights.values()))) {
|
||||
DeviceResponse deviceResponse = null;
|
||||
if(!light.isInactive()) {
|
||||
if (light.containsType(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) {
|
||||
CallItem[] callItems = null;
|
||||
try {
|
||||
if(light.getOnUrl() != null)
|
||||
callItems = aGsonBuilder.fromJson(light.getOnUrl(), CallItem[].class);
|
||||
} catch(JsonSyntaxException e) {
|
||||
log.warn("Could not decode Json for url items to get Hue state for device: " + light.getName());
|
||||
callItems = null;
|
||||
}
|
||||
|
||||
for (int i = 0; callItems != null && i < callItems.length; i++) {
|
||||
if((callItems[i].getType() != null && callItems[i].getType().equals(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) ||
|
||||
(callItems[i].getItem() != null && callItems[i].getItem().getAsString() != null && callItems[i].getItem().getAsString().contains("hueName"))) {
|
||||
deviceResponse = myHueHome.getHueDeviceInfo(callItems[i], light);
|
||||
i = callItems.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (deviceResponse == null) {
|
||||
deviceResponse = DeviceResponse.createResponse(light);
|
||||
}
|
||||
deviceResponseMap.put(light.getId(), deviceResponse);
|
||||
}
|
||||
}
|
||||
return (deviceResponseMap.size() == 0) ? null : deviceResponseMap;
|
||||
}
|
||||
|
||||
public DeviceDescriptor findOne(String id) {
|
||||
return devices.get(id);
|
||||
}
|
||||
|
||||
147
src/main/java/com/bwssystems/HABridge/dao/GroupDescriptor.java
Normal file
147
src/main/java/com/bwssystems/HABridge/dao/GroupDescriptor.java
Normal file
@@ -0,0 +1,147 @@
|
||||
package com.bwssystems.HABridge.dao;
|
||||
|
||||
import com.bwssystems.HABridge.api.hue.DeviceState;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.bwssystems.HABridge.api.hue.GroupState;
|
||||
|
||||
/*
|
||||
* Object to handle the device configuration
|
||||
*/
|
||||
public class GroupDescriptor{
|
||||
@SerializedName("id")
|
||||
@Expose
|
||||
private String id;
|
||||
@SerializedName("name")
|
||||
@Expose
|
||||
private String name;
|
||||
@SerializedName("groupType")
|
||||
@Expose
|
||||
private String groupType;
|
||||
@SerializedName("groupClass")
|
||||
@Expose
|
||||
private String groupClass;
|
||||
@SerializedName("requesterAddress")
|
||||
@Expose
|
||||
private String requesterAddress;
|
||||
@SerializedName("inactive")
|
||||
@Expose
|
||||
private boolean inactive;
|
||||
@SerializedName("description")
|
||||
@Expose
|
||||
private String description;
|
||||
@SerializedName("comments")
|
||||
@Expose
|
||||
private String comments;
|
||||
|
||||
private DeviceState action;
|
||||
private GroupState groupState;
|
||||
|
||||
@SerializedName("lights")
|
||||
@Expose
|
||||
private String[] lights;
|
||||
@SerializedName("exposeAsLight")
|
||||
@Expose
|
||||
private String exposeAsLight;
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getGroupType() {
|
||||
return groupType;
|
||||
}
|
||||
|
||||
public void setGroupType(String groupType) {
|
||||
this.groupType = groupType;
|
||||
}
|
||||
|
||||
public String getGroupClass() {
|
||||
return groupClass;
|
||||
}
|
||||
|
||||
public void setGroupClass(String groupClass) {
|
||||
this.groupClass = groupClass;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public GroupState getGroupState() {
|
||||
if(groupState == null)
|
||||
groupState = new GroupState(false,false);
|
||||
return groupState;
|
||||
}
|
||||
|
||||
public void setGroupState(GroupState groupState) {
|
||||
this.groupState = groupState;
|
||||
}
|
||||
|
||||
public DeviceState getAction() {
|
||||
if(action == null)
|
||||
action = DeviceState.createDeviceState(true);
|
||||
return action;
|
||||
}
|
||||
|
||||
public void setAction(DeviceState action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public boolean isInactive() {
|
||||
return inactive;
|
||||
}
|
||||
|
||||
public void setInactive(boolean inactive) {
|
||||
this.inactive = inactive;
|
||||
}
|
||||
|
||||
public String getRequesterAddress() {
|
||||
return requesterAddress;
|
||||
}
|
||||
|
||||
public void setRequesterAddress(String requesterAddress) {
|
||||
this.requesterAddress = requesterAddress;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getComments() {
|
||||
return comments;
|
||||
}
|
||||
|
||||
public void setComments(String comments) {
|
||||
this.comments = comments;
|
||||
}
|
||||
|
||||
public String[] getLights() {
|
||||
return lights;
|
||||
}
|
||||
|
||||
public void setLights(String[] lights) {
|
||||
this.lights = lights;
|
||||
}
|
||||
|
||||
public void setExposeAsLight(String exposeFor) {
|
||||
this.exposeAsLight = exposeFor;
|
||||
}
|
||||
|
||||
public String getExposeAsLight() {
|
||||
return exposeAsLight;
|
||||
}
|
||||
}
|
||||
220
src/main/java/com/bwssystems/HABridge/dao/GroupRepository.java
Normal file
220
src/main/java/com/bwssystems/HABridge/dao/GroupRepository.java
Normal file
@@ -0,0 +1,220 @@
|
||||
package com.bwssystems.HABridge.dao;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.dao.GroupDescriptor;
|
||||
import com.bwssystems.HABridge.util.BackupHandler;
|
||||
import com.bwssystems.HABridge.util.JsonTransformer;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import java.util.List;
|
||||
/*
|
||||
* This is an in memory list to manage the configured groups and saves the list as a JSON string to a file for later
|
||||
* loading.
|
||||
*/
|
||||
public class GroupRepository extends BackupHandler {
|
||||
private Map<String, GroupDescriptor> groups;
|
||||
private Path repositoryPath;
|
||||
private Gson gson;
|
||||
private Integer nextId;
|
||||
private Logger log = LoggerFactory.getLogger(GroupRepository.class);
|
||||
|
||||
public GroupRepository(String groupDb) {
|
||||
super();
|
||||
gson =
|
||||
new GsonBuilder()
|
||||
.excludeFieldsWithoutExposeAnnotation()
|
||||
.create();
|
||||
nextId = 0;
|
||||
try {
|
||||
repositoryPath = null;
|
||||
repositoryPath = Paths.get(groupDb);
|
||||
setupParams(repositoryPath, ".bk", "group.db-");
|
||||
_loadRepository(repositoryPath);
|
||||
} catch (Exception ex) {
|
||||
groups = new HashMap<String, GroupDescriptor>();
|
||||
}
|
||||
}
|
||||
|
||||
public void loadRepository() {
|
||||
if(repositoryPath != null)
|
||||
_loadRepository(repositoryPath);
|
||||
}
|
||||
private void _loadRepository(Path aPath){
|
||||
String jsonContent = repositoryReader(aPath);
|
||||
groups = new HashMap<String, GroupDescriptor>();
|
||||
|
||||
if(jsonContent != null)
|
||||
{
|
||||
GroupDescriptor list[] = gson.fromJson(jsonContent, GroupDescriptor[].class);
|
||||
for(int i = 0; i < list.length; i++) {
|
||||
list[i].setGroupState(null);
|
||||
put(list[i].getId(), list[i]);
|
||||
if(Integer.decode(list[i].getId()) > nextId) {
|
||||
nextId = Integer.decode(list[i].getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<GroupDescriptor> findAll() {
|
||||
List<GroupDescriptor> list = new ArrayList<GroupDescriptor>(groups.values());
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<GroupDescriptor> findActive() {
|
||||
List<GroupDescriptor> list = new ArrayList<GroupDescriptor>();
|
||||
for(GroupDescriptor aGroup : new ArrayList<GroupDescriptor>(groups.values())) {
|
||||
if(!aGroup.isInactive())
|
||||
list.add(aGroup);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<GroupDescriptor> findAllByRequester(String anAddress) {
|
||||
List<GroupDescriptor> list = new ArrayList<GroupDescriptor>(groups.values());
|
||||
List<GroupDescriptor> theReturnList = new ArrayList<GroupDescriptor>();
|
||||
Iterator<GroupDescriptor> anIterator = list.iterator();
|
||||
GroupDescriptor theGroup;
|
||||
String theRequesterAddress;
|
||||
|
||||
HashMap<String,String > addressMap;
|
||||
while (anIterator.hasNext()) {
|
||||
theGroup = anIterator.next();
|
||||
theRequesterAddress = theGroup.getRequesterAddress();
|
||||
addressMap = new HashMap<String, String>();
|
||||
if(theRequesterAddress != null) {
|
||||
if (theRequesterAddress.contains(",")) {
|
||||
String[] theArray = theRequesterAddress.split(",");
|
||||
for (String v : theArray) {
|
||||
addressMap.put(v.trim(), v.trim());
|
||||
}
|
||||
} else
|
||||
addressMap.put(theRequesterAddress, theRequesterAddress);
|
||||
}
|
||||
if (theRequesterAddress == null || theRequesterAddress.length() == 0 || addressMap.containsKey(anAddress))
|
||||
theReturnList.add(theGroup);
|
||||
}
|
||||
return theReturnList;
|
||||
}
|
||||
|
||||
public List<GroupDescriptor> findVirtualLights(String anAddress) {
|
||||
List<GroupDescriptor> list = new ArrayList<GroupDescriptor>();
|
||||
for (GroupDescriptor group : groups.values()) {
|
||||
String expose = group.getExposeAsLight();
|
||||
if (expose != null && expose.contains(anAddress)) {
|
||||
list.add(group);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public GroupDescriptor findOne(String id) {
|
||||
return groups.get(id);
|
||||
}
|
||||
|
||||
private void put(String id, GroupDescriptor aDescriptor) {
|
||||
groups.put(id, aDescriptor);
|
||||
}
|
||||
|
||||
public void save() {
|
||||
save(groups.values().toArray(new GroupDescriptor[0]));
|
||||
}
|
||||
|
||||
public void save(GroupDescriptor[] descriptors) {
|
||||
String theNames = "";
|
||||
for(int i = 0; i < descriptors.length; i++) {
|
||||
if(descriptors[i].getId() != null && descriptors[i].getId().length() > 0)
|
||||
groups.remove(descriptors[i].getId());
|
||||
else {
|
||||
nextId++;
|
||||
descriptors[i].setId(String.valueOf(nextId));
|
||||
}
|
||||
|
||||
put(descriptors[i].getId(), descriptors[i]);
|
||||
theNames = theNames + " " + descriptors[i].getName() + ", ";
|
||||
}
|
||||
String jsonValue = gson.toJson(findAll());
|
||||
repositoryWriter(jsonValue, repositoryPath);
|
||||
log.debug("Save group(s): " + theNames);
|
||||
}
|
||||
|
||||
public Integer getNewId() {
|
||||
return nextId + 1;
|
||||
}
|
||||
|
||||
public String delete(GroupDescriptor aDescriptor) {
|
||||
if (aDescriptor != null) {
|
||||
groups.remove(aDescriptor.getId());
|
||||
JsonTransformer aRenderer = new JsonTransformer();
|
||||
String jsonValue = aRenderer.render(findAll());
|
||||
repositoryWriter(jsonValue, repositoryPath);
|
||||
return "Group with id '" + aDescriptor.getId() + "' deleted";
|
||||
} else {
|
||||
return "Group not found";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void repositoryWriter(String content, Path filePath) {
|
||||
if(Files.exists(filePath) && !Files.isWritable(filePath)){
|
||||
log.error("Error file is not writable: " + filePath);
|
||||
return;
|
||||
}
|
||||
|
||||
if(Files.notExists(filePath.getParent())) {
|
||||
try {
|
||||
Files.createDirectories(filePath.getParent());
|
||||
} catch (IOException e) {
|
||||
log.error("Error creating the directory: " + filePath + " message: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Path target = null;
|
||||
if(Files.exists(filePath)) {
|
||||
target = FileSystems.getDefault().getPath(filePath.getParent().toString(), "group.db.old");
|
||||
Files.move(filePath, target);
|
||||
}
|
||||
Files.write(filePath, content.getBytes(), StandardOpenOption.CREATE);
|
||||
if(target != null)
|
||||
Files.delete(target);
|
||||
} catch (IOException e) {
|
||||
log.error("Error writing the file: " + filePath + " message: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private String repositoryReader(Path filePath) {
|
||||
|
||||
String content = null;
|
||||
if(Files.notExists(filePath) || !Files.isReadable(filePath)){
|
||||
log.warn("Error reading the file: " + filePath + " - Does not exist or is not readable. continuing...");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
content = new String(Files.readAllBytes(filePath));
|
||||
} catch (IOException e) {
|
||||
log.error("Error reading the file: " + filePath + " message: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.BackupFilename;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.dao.DeviceRepository;
|
||||
import com.bwssystems.HABridge.dao.GroupRepository;
|
||||
import com.bwssystems.HABridge.dao.ErrorMessage;
|
||||
import com.bwssystems.HABridge.util.JsonTransformer;
|
||||
import com.google.gson.Gson;
|
||||
@@ -38,6 +39,7 @@ public class DeviceResource {
|
||||
private static final String API_CONTEXT = "/api/devices";
|
||||
private static final Logger log = LoggerFactory.getLogger(DeviceResource.class);
|
||||
private DeviceRepository deviceRepository;
|
||||
private GroupRepository groupRepository;
|
||||
private HomeManager homeManager;
|
||||
private BridgeSettings bridgeSettings;
|
||||
private Gson aGsonHandler;
|
||||
@@ -46,6 +48,7 @@ public class DeviceResource {
|
||||
public DeviceResource(BridgeSettings theSettings, HomeManager aHomeManager) {
|
||||
bridgeSettings = theSettings;
|
||||
this.deviceRepository = new DeviceRepository(bridgeSettings.getBridgeSettingsDescriptor().getUpnpDeviceDb());
|
||||
this.groupRepository = new GroupRepository(bridgeSettings.getBridgeSettingsDescriptor().getUpnpGroupDb());
|
||||
homeManager = aHomeManager;
|
||||
aGsonHandler = new GsonBuilder().create();
|
||||
setupEndpoints();
|
||||
@@ -55,6 +58,10 @@ public class DeviceResource {
|
||||
return deviceRepository;
|
||||
}
|
||||
|
||||
public GroupRepository getGroupRepository() {
|
||||
return groupRepository;
|
||||
}
|
||||
|
||||
private void setupEndpoints() {
|
||||
log.info("HABridge device management service started.... ");
|
||||
before(API_CONTEXT + "/*", (request, response) -> {
|
||||
@@ -84,6 +91,7 @@ public class DeviceResource {
|
||||
else {
|
||||
devices = new Gson().fromJson("[" + request.body() + "]", DeviceDescriptor[].class);
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
CallItem[] callItems = null;
|
||||
String errorMessage = null;
|
||||
for(int i = 0; i < devices.length; i++) {
|
||||
@@ -122,6 +130,15 @@ public class DeviceResource {
|
||||
log.debug(errorMessage);
|
||||
return new ErrorMessage(errorMessage);
|
||||
}
|
||||
try {
|
||||
if(devices[i].getColorUrl() != null && !devices[i].getColorUrl().isEmpty())
|
||||
callItems = aGsonHandler.fromJson(devices[i].getColorUrl(), CallItem[].class);
|
||||
} catch(JsonSyntaxException e) {
|
||||
response.status(HttpStatus.SC_BAD_REQUEST);
|
||||
errorMessage = "Bad color URL JSON in create device(s) for name: " + devices[i].getName() + " with color URL: " + devices[i].getColorUrl();
|
||||
log.debug(errorMessage);
|
||||
return new ErrorMessage(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
deviceRepository.save(devices);
|
||||
@@ -214,6 +231,18 @@ public class DeviceResource {
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return homeManager.findResource(DeviceMapTypes.VERA_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.VERA_SCENE[DeviceMapTypes.typeIndex]);
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/fibaro/devices", "application/json", (request, response) -> {
|
||||
log.debug("Get fibaro devices");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return homeManager.findResource(DeviceMapTypes.FIBARO_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.FIBARO_DEVICE[DeviceMapTypes.typeIndex]);
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/fibaro/scenes", "application/json", (request, response) -> {
|
||||
log.debug("Get fibaro scenes");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return homeManager.findResource(DeviceMapTypes.FIBARO_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.FIBARO_SCENE[DeviceMapTypes.typeIndex]);
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/harmony/activities", "application/json", (request, response) -> {
|
||||
log.debug("Get harmony activities");
|
||||
@@ -262,6 +291,12 @@ public class DeviceResource {
|
||||
return homeManager.findResource(DeviceMapTypes.HASS_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.HASS_DEVICE[DeviceMapTypes.typeIndex]);
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/homewizard/devices", "application/json", (request, response) -> {
|
||||
log.debug("Get HomeWizard Clients");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return homeManager.findResource(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex]);
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/domoticz/devices", "application/json", (request, response) -> {
|
||||
log.debug("Get Domoticz Clients");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
@@ -280,11 +315,37 @@ public class DeviceResource {
|
||||
return homeManager.findResource(DeviceMapTypes.SOMFY_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.SOMFY_DEVICE[DeviceMapTypes.typeIndex]);
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/openhab/devices", "application/json", (request, response) -> {
|
||||
log.debug("Get OpenHAB devices");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return homeManager.findResource(DeviceMapTypes.OPENHAB_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.OPENHAB_DEVICE[DeviceMapTypes.typeIndex]);
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/fhem/devices", "application/json", (request, response) -> {
|
||||
log.debug("Get FHEM devices");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return homeManager.findResource(DeviceMapTypes.FHEM_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.FHEM_DEVICE[DeviceMapTypes.typeIndex]);
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/broadlink/devices", "application/json", (request, response) -> {
|
||||
log.debug("Get Broadlink devices");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return homeManager.findResource(DeviceMapTypes.BROADLINK_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.BROADLINK_DEVICE[DeviceMapTypes.typeIndex]);
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/map/types", "application/json", (request, response) -> {
|
||||
log.debug("Get map types");
|
||||
return new DeviceMapTypes().getDeviceMapTypes();
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/refresh/:typeIndex", "application/json", (request, response) -> {
|
||||
String typeIndex = request.params(":typeIndex");
|
||||
log.debug("Refresh Home: " + typeIndex);
|
||||
response.status(HttpStatus.SC_OK);
|
||||
homeManager.findResource(typeIndex).refresh();
|
||||
return null;
|
||||
}, new JsonTransformer());
|
||||
|
||||
// http://ip_address:port/api/devices/exec/renumber CORS request
|
||||
options(API_CONTEXT + "/exec/renumber", "application/json", (request, response) -> {
|
||||
response.status(HttpStatus.SC_OK);
|
||||
|
||||
@@ -2,4 +2,5 @@ package com.bwssystems.HABridge.devicemanagmeent;
|
||||
|
||||
public interface ResourceHandler {
|
||||
public Object getItems(String type);
|
||||
public void refresh();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.bwssystems.HABridge.hue;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.Conversion;
|
||||
@@ -51,11 +52,22 @@ public class BrightnessDecode {
|
||||
boolean notDone = true;
|
||||
String replaceValue = null;
|
||||
String replaceTarget = null;
|
||||
int percentBrightness = (int) Math.round(intensity / 255.0 * 100);
|
||||
float decimalBrightness = (float) (intensity / 255.0);
|
||||
int percentBrightness = 0;
|
||||
float decimalBrightness = (float) 0.0;
|
||||
Map<String, BigDecimal> variables = new HashMap<String, BigDecimal>();
|
||||
String mathDescriptor = null;
|
||||
|
||||
|
||||
if(intensity > 0) {
|
||||
decimalBrightness = (float) (intensity / 255.0);
|
||||
if(intensity > 0 && intensity < 5)
|
||||
percentBrightness = 1;
|
||||
else
|
||||
percentBrightness = (int) Math.round(intensity / 255.0 * 100);
|
||||
} else {
|
||||
decimalBrightness = (float) 0.0;
|
||||
percentBrightness = 0;
|
||||
}
|
||||
|
||||
while(notDone) {
|
||||
notDone = false;
|
||||
if (request.contains(INTENSITY_BYTE)) {
|
||||
@@ -83,7 +95,7 @@ public class BrightnessDecode {
|
||||
replaceTarget = INTENSITY_PERCENT_HEX;
|
||||
notDone = true;
|
||||
} else if (request.contains(INTENSITY_DECIMAL_PERCENT)) {
|
||||
replaceValue = String.format("%1.2f", decimalBrightness);
|
||||
replaceValue = String.format(Locale.ROOT, "%1.2f", decimalBrightness);
|
||||
replaceTarget = INTENSITY_DECIMAL_PERCENT;
|
||||
notDone = true;
|
||||
} else if (request.contains(INTENSITY_MATH_CLOSE)) {
|
||||
@@ -110,11 +122,7 @@ public class BrightnessDecode {
|
||||
|
||||
Integer endResult = calculateMath(variables, mathDescriptor);
|
||||
if(endResult != null) {
|
||||
if (isHex) {
|
||||
replaceValue = convertToHex(endResult);
|
||||
} else {
|
||||
replaceValue = endResult.toString();
|
||||
}
|
||||
replaceValue = convertToHex(endResult);
|
||||
replaceTarget = INTENSITY_MATH + mathDescriptor + INTENSITY_MATH_CLOSE_HEX;
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
22
src/main/java/com/bwssystems/HABridge/hue/ColorData.java
Normal file
22
src/main/java/com/bwssystems/HABridge/hue/ColorData.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.bwssystems.HABridge.hue;
|
||||
|
||||
public class ColorData {
|
||||
public enum ColorMode { XY, CT, HS}
|
||||
|
||||
private ColorMode mode;
|
||||
private Object data;
|
||||
|
||||
public ColorData(ColorMode mode, Object value) {
|
||||
this.mode = mode;
|
||||
this.data = value;
|
||||
}
|
||||
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public ColorMode getColorMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +1,274 @@
|
||||
package com.bwssystems.HABridge.hue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
|
||||
public class ColorDecode {
|
||||
private static final Logger log = LoggerFactory.getLogger(ColorDecode.class);
|
||||
private static final String COLOR_R = "${color.r}";
|
||||
private static final String COLOR_G = "${color.g}";
|
||||
private static final String COLOR_B = "${color.b}";
|
||||
private static final String COLOR_RX = "${color.rx}";
|
||||
private static final String COLOR_GX = "${color.gx}";
|
||||
private static final String COLOR_BX = "${color.bx}";
|
||||
private static final String COLOR_RGBX = "${color.rgbx}";
|
||||
private static final Pattern COLOR_MILIGHT = Pattern.compile("\\$\\{color.milight\\:([01234])\\}");
|
||||
|
||||
public static String convertCIEtoRGB(List<Double> xy) {
|
||||
double x;
|
||||
double y;
|
||||
double Y;
|
||||
public static List<Integer> convertCIEtoRGB(List<Double> xy, int brightness) {
|
||||
List<Integer> rgb;
|
||||
double x = xy.get(0); // the given x value
|
||||
double y = xy.get(1); // the given y value
|
||||
double z = 1.0 - x - y;
|
||||
double Y = (double)brightness/(double)254.00; // The given brightness value
|
||||
double X = (Y / y) * x;
|
||||
double Z = (Y / y) * z;
|
||||
|
||||
double r = X * 1.656492 - Y * 0.354851 - Z * 0.255038;
|
||||
double g = -X * 0.707196 + Y * 1.655397 + Z * 0.036152;
|
||||
double b = X * 0.051713 - Y * 0.121364 + Z * 1.011530;
|
||||
|
||||
if (r > b && r > g && r > 1.0) {
|
||||
|
||||
g = g / r;
|
||||
b = b / r;
|
||||
r = 1.0;
|
||||
}
|
||||
else if (g > b && g > r && g > 1.0) {
|
||||
|
||||
r = r / g;
|
||||
b = b / g;
|
||||
g = 1.0;
|
||||
}
|
||||
else if (b > r && b > g && b > 1.0) {
|
||||
|
||||
r = r / b;
|
||||
g = g / b;
|
||||
b = 1.0;
|
||||
}
|
||||
|
||||
|
||||
r = r <= 0.0031308 ? 12.92 * r : (1.0 + 0.055) * Math.pow(r, (1.0 / 2.4)) - 0.055;
|
||||
g = g <= 0.0031308 ? 12.92 * g : (1.0 + 0.055) * Math.pow(g, (1.0 / 2.4)) - 0.055;
|
||||
b = b <= 0.0031308 ? 12.92 * b : (1.0 + 0.055) * Math.pow(b, (1.0 / 2.4)) - 0.055;
|
||||
|
||||
x = xy.get(0) * 100;
|
||||
y = xy.get(1) * 100;
|
||||
Y= y;
|
||||
double R = 3.240479*((x*Y)/y) + -1.537150*Y + -0.498535*(((1-x-y)*Y)/y);
|
||||
double G = -0.969256*((x*Y)/y) + 1.875992*Y + 0.041556*(((1-x-y)*Y)/y);
|
||||
double B = 0.055648*((x*Y)/y) + -0.204043*Y + 1.057311*(((1-x-y)*Y)/y);
|
||||
if (r > b && r > g) {
|
||||
// red is biggest
|
||||
if (r > 1.0) {
|
||||
g = g / r;
|
||||
b = b / r;
|
||||
r = 1.0;
|
||||
}
|
||||
}
|
||||
else if (g > b && g > r) {
|
||||
// green is biggest
|
||||
if (g > 1.0) {
|
||||
r = r / g;
|
||||
b = b / g;
|
||||
g = 1.0;
|
||||
}
|
||||
}
|
||||
else if (b > r && b > g) {
|
||||
// blue is biggest
|
||||
if (b > 1.0) {
|
||||
r = r / b;
|
||||
g = g / b;
|
||||
b = 1.0;
|
||||
}
|
||||
}
|
||||
if(r < 0.0)
|
||||
r = 0;
|
||||
if(g < 0.0)
|
||||
g = 0;
|
||||
if(b < 0.0)
|
||||
b = 0;
|
||||
|
||||
rgb = new ArrayList<Integer>();
|
||||
rgb.add((int)Math.round(r * 255));
|
||||
rgb.add((int)Math.round(g * 255));
|
||||
rgb.add((int)Math.round(b * 255));
|
||||
log.debug("Color change with XY: " + x + " " + y + " Resulting RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " " + rgb.get(2));
|
||||
return rgb;
|
||||
}
|
||||
|
||||
// took that approximation from http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/
|
||||
public static List<Integer> convertCTtoRGB(Integer ct) {
|
||||
double temperature = 1000000.0 / (double)ct;
|
||||
temperature /= 100;
|
||||
double r,g,b;
|
||||
if (temperature <= 66) {
|
||||
r = 255;
|
||||
g = temperature;
|
||||
g = 99.4708025861 * Math.log(g) - 161.1195681661;
|
||||
} else {
|
||||
r = temperature - 60;
|
||||
r = 329.698727446 * (Math.pow(r, -0.1332047592));
|
||||
g = temperature - 60;
|
||||
g = 288.1221695283 * (Math.pow(g, -0.0755148492));
|
||||
}
|
||||
|
||||
if (temperature >= 66) {
|
||||
b = 255;
|
||||
} else {
|
||||
if (temperature <= 19) {
|
||||
b = 0;
|
||||
} else {
|
||||
b = temperature - 10;
|
||||
b = 138.5177312231 * Math.log(b) - 305.0447927307;
|
||||
}
|
||||
}
|
||||
r = assureBounds(r);
|
||||
g = assureBounds(g);
|
||||
b = assureBounds(b);
|
||||
List<Integer> rgb = new ArrayList<Integer>();
|
||||
rgb.add((int)Math.round(r));
|
||||
rgb.add((int)Math.round(g));
|
||||
rgb.add((int)Math.round(b));
|
||||
log.debug("Color change with CT: " + ct + ". Resulting RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " " + rgb.get(2));
|
||||
return rgb;
|
||||
}
|
||||
|
||||
private static double assureBounds(double value) {
|
||||
if (value < 0.0) {
|
||||
value = 0;
|
||||
}
|
||||
if (value > 255.0) {
|
||||
value = 255;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static String replaceColorData(String request, ColorData colorData, int setIntensity, boolean isHex) {
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
if (colorData == null) {
|
||||
return request;
|
||||
}
|
||||
boolean notDone = true;
|
||||
ColorData.ColorMode colorMode = colorData.getColorMode();
|
||||
List<Integer> rgb = null;
|
||||
if (colorMode == ColorData.ColorMode.XY) {
|
||||
rgb = convertCIEtoRGB((List<Double>)colorData.getData(), setIntensity);
|
||||
} else if (colorMode == ColorData.ColorMode.CT) {
|
||||
rgb = convertCTtoRGB((Integer)colorData.getData());
|
||||
}
|
||||
|
||||
return null;
|
||||
while(notDone) {
|
||||
notDone = false;
|
||||
if (request.contains(COLOR_R)) {
|
||||
request = request.replace(COLOR_R, isHex ? String.format("%02X", rgb.get(0)) : String.valueOf(rgb.get(0)));
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(COLOR_G)) {
|
||||
request = request.replace(COLOR_G, isHex ? String.format("%02X", rgb.get(1)) : String.valueOf(rgb.get(1)));
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(COLOR_B)) {
|
||||
request = request.replace(COLOR_B, isHex ? String.format("%02X", rgb.get(2)) : String.valueOf(rgb.get(2)));
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(COLOR_RX)) {
|
||||
request = request.replace(COLOR_RX, String.format("%02X", rgb.get(0)));
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(COLOR_GX)) {
|
||||
request = request.replace(COLOR_GX, String.format("%02X", rgb.get(1)));
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(COLOR_BX)) {
|
||||
request = request.replace(COLOR_BX, String.format("%02X", rgb.get(2)));
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(COLOR_RGBX)) {
|
||||
request = request.replace(COLOR_RGBX, String.format("%02X%02X%02X", rgb.get(0), rgb.get(1), rgb.get(2)));
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
Matcher m = COLOR_MILIGHT.matcher(request);
|
||||
while (m.find()) {
|
||||
int group = Integer.parseInt(m.group(1));
|
||||
request = m.replaceFirst(getMilightV5FromRgb(rgb, group));
|
||||
m.reset(request);
|
||||
}
|
||||
|
||||
log.debug("Request <<" + request + ">>, not done: " + notDone);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
private static String getMilightV5FromRgb(List<Integer> rgb, int group) {
|
||||
double r = (double)rgb.get(0);
|
||||
double g = (double)rgb.get(1);
|
||||
double b = (double)rgb.get(2);
|
||||
if (r > 245 && g > 245 && b > 245) { // it's white
|
||||
String retVal = "";
|
||||
if (group == 0) {
|
||||
retVal += "C2";
|
||||
} else if (group == 1) {
|
||||
retVal += "C5";
|
||||
} else if (group == 2) {
|
||||
retVal += "C7";
|
||||
} else if (group == 3) {
|
||||
retVal += "C9";
|
||||
} else if (group == 4) {
|
||||
retVal += "CB";
|
||||
}
|
||||
log.debug("Convert RGB to Milight. Result: WHITE. RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " " + rgb.get(2));
|
||||
return retVal + "0055";
|
||||
} else { // normal color
|
||||
r /= (double)0xFF;
|
||||
g /= (double)0xFF;
|
||||
b /= (double)0xFF;
|
||||
double max = Math.max(Math.max(r, g), b), min = Math.min(Math.min(r, g), b);
|
||||
double h = 0;
|
||||
double d = max - min;
|
||||
|
||||
if (max == min) {
|
||||
h = 0;
|
||||
} else {
|
||||
if (max == r) {
|
||||
h = ((g - b) / d + (g < b ? 6 : 0));
|
||||
} else if (max == g) {
|
||||
h = ((b - r) / d + 2);
|
||||
} else if (max == b){
|
||||
h = ((r - g) / d + 4);
|
||||
}
|
||||
h = Math.round(h * 60);
|
||||
}
|
||||
int milight = (int)((256 + 176 - Math.floor(h / 360.0 * 255.0)) % 256);
|
||||
log.debug("Convert RGB to Milight. Result: " + milight + " RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " " + rgb.get(2));
|
||||
return "40" + String.format("%02X", milight) + "55";
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static int getIntRGB(ColorData colorData, int setIntensity) {
|
||||
ColorData.ColorMode colorMode = colorData.getColorMode();
|
||||
List<Integer> rgb = null;
|
||||
if (colorMode == ColorData.ColorMode.XY) {
|
||||
rgb = convertCIEtoRGB((List<Double>) colorData.getData(), setIntensity);
|
||||
} else if (colorMode == ColorData.ColorMode.CT) {
|
||||
rgb = convertCTtoRGB((Integer) colorData.getData());
|
||||
}
|
||||
|
||||
int rgbIntVal = Integer.parseInt(String.format("%02X%02X%02X", rgb.get(0), rgb.get(1), rgb.get(2)), 16);
|
||||
log.debug("Convert RGB to int. Result: " + rgbIntVal + " RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " "
|
||||
+ rgb.get(2));
|
||||
return rgbIntVal;
|
||||
}
|
||||
}
|
||||
|
||||
75
src/main/java/com/bwssystems/HABridge/hue/ColorMap.java
Normal file
75
src/main/java/com/bwssystems/HABridge/hue/ColorMap.java
Normal file
@@ -0,0 +1,75 @@
|
||||
package com.bwssystems.HABridge.hue;
|
||||
|
||||
public class ColorMap {
|
||||
private double red;
|
||||
private double green;
|
||||
private double blue;
|
||||
private long R;
|
||||
private long G;
|
||||
private long B;
|
||||
private double X;
|
||||
private double Y;
|
||||
private Double Z;
|
||||
private double z;
|
||||
public double getRed() {
|
||||
return red;
|
||||
}
|
||||
public void setRed(double red) {
|
||||
this.red = red;
|
||||
}
|
||||
public double getGreen() {
|
||||
return green;
|
||||
}
|
||||
public void setGreen(double green) {
|
||||
this.green = green;
|
||||
}
|
||||
public double getBlue() {
|
||||
return blue;
|
||||
}
|
||||
public void setBlue(double blue) {
|
||||
this.blue = blue;
|
||||
}
|
||||
public long getR() {
|
||||
return R;
|
||||
}
|
||||
public void setR(long r) {
|
||||
R = r;
|
||||
}
|
||||
public long getG() {
|
||||
return G;
|
||||
}
|
||||
public void setG(long g) {
|
||||
G = g;
|
||||
}
|
||||
public long getB() {
|
||||
return B;
|
||||
}
|
||||
public void setB(long b) {
|
||||
B = b;
|
||||
}
|
||||
public double getX() {
|
||||
return X;
|
||||
}
|
||||
public void setX(double x) {
|
||||
X = x;
|
||||
}
|
||||
public double getY() {
|
||||
return Y;
|
||||
}
|
||||
public void setY(double y) {
|
||||
Y = y;
|
||||
}
|
||||
public Double getZ() {
|
||||
return Z;
|
||||
}
|
||||
public void setZ(Double z) {
|
||||
Z = z;
|
||||
}
|
||||
public double getz() {
|
||||
return z;
|
||||
}
|
||||
public void setz(double z) {
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,6 +14,9 @@ public class DeviceDataDecode {
|
||||
private static final String DEVICE_MAPTYPE = "${device.mapType}";
|
||||
private static final String DEVICE_DEVICETYPE = "${device.deviceType}";
|
||||
private static final String DEVICE_TARGETDEVICE = "${device.targetDevice}";
|
||||
private static final String DEVICE_REQUESTERADDRESS = "${device.requesterAddress}";
|
||||
private static final String DEVICE_DESCRIPTION = "${device.description}";
|
||||
private static final String DEVICE_COMMENTS = "${device.comments}";
|
||||
|
||||
public static String replaceDeviceData(String request, DeviceDescriptor device) {
|
||||
if (request == null) {
|
||||
@@ -58,6 +61,21 @@ public class DeviceDataDecode {
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(DEVICE_REQUESTERADDRESS)) {
|
||||
request = request.replace(DEVICE_REQUESTERADDRESS, device.getRequesterAddress());
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(DEVICE_DESCRIPTION)) {
|
||||
request = request.replace(DEVICE_DESCRIPTION, device.getDescription());
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(DEVICE_COMMENTS)) {
|
||||
request = request.replace(DEVICE_COMMENTS, device.getComments());
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
log.debug("Request <<" + request + ">>, not done: " + notDone);
|
||||
}
|
||||
return request;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,8 @@ package com.bwssystems.HABridge.hue;
|
||||
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
|
||||
public interface HueMulatorHandler {
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity, Integer targetBri, Integer targetBriInc, DeviceDescriptor device, String body);
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity, Integer targetBri, Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory;
|
||||
public class TimeDecode {
|
||||
private static final Logger log = LoggerFactory.getLogger(TimeDecode.class);
|
||||
private static final String TIME_FORMAT = "${time.format(";
|
||||
private static final String TIMESTAMP = "${time.millis}";
|
||||
private static final String TIME_FORMAT_CLOSE = ")}";
|
||||
|
||||
/*
|
||||
@@ -38,6 +39,10 @@ public class TimeDecode {
|
||||
log.warn("Could not format current time: " + timeFormatDescriptor, e);
|
||||
}
|
||||
}
|
||||
if (request.contains(TIMESTAMP)) {
|
||||
request = request.replace(TIMESTAMP, String.valueOf(System.currentTimeMillis()));
|
||||
notDone = true;
|
||||
}
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.bwssystems.HABridge.DeviceMapTypes;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.nest.controller.Home;
|
||||
import com.bwssystems.nest.controller.Nest;
|
||||
@@ -31,10 +32,13 @@ public class NestHome implements com.bwssystems.HABridge.Home {
|
||||
private Gson aGsonHandler;
|
||||
private Boolean isFarenheit;
|
||||
private Boolean validNest;
|
||||
private boolean closed;
|
||||
|
||||
public NestHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,17 +96,23 @@ public class NestHome implements com.bwssystems.HABridge.Home {
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
if(theSession != null) {
|
||||
theNest.endNestSession();
|
||||
}
|
||||
theNest = null;
|
||||
theSession = null;
|
||||
nestItems = null;
|
||||
closed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
String responseString = null;
|
||||
log.debug("executing HUE api request to set away for nest " + anItem.getType() + ": " + anItem.getItem().toString());
|
||||
if(!validNest) {
|
||||
@@ -187,5 +197,10 @@ public class NestHome implements com.bwssystems.HABridge.Home {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.bwssystems.HABridge.plugins.broadlink;
|
||||
|
||||
public class BroadlinkEntry {
|
||||
private String name;
|
||||
private String id;
|
||||
private String ipAddr;
|
||||
private String macAddr;
|
||||
private String command;
|
||||
private String data;
|
||||
private String type;
|
||||
private String baseType;
|
||||
private String desc;
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
public String getIpAddr() {
|
||||
return ipAddr;
|
||||
}
|
||||
public void setIpAddr(String ipAddr) {
|
||||
this.ipAddr = ipAddr;
|
||||
}
|
||||
public String getMacAddr() {
|
||||
return macAddr;
|
||||
}
|
||||
public void setMacAddr(String macAddr) {
|
||||
this.macAddr = macAddr;
|
||||
}
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
public void setCommand(String command) {
|
||||
this.command = command;
|
||||
}
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
public String getBaseType() {
|
||||
return baseType;
|
||||
}
|
||||
public void setBaseType(String baseType) {
|
||||
this.baseType = baseType;
|
||||
}
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
public boolean hasIpAndMac() {
|
||||
boolean deviceOk = true;
|
||||
if(ipAddr == null || ipAddr.trim().isEmpty())
|
||||
deviceOk = false;
|
||||
else if(macAddr == null || macAddr.trim().isEmpty())
|
||||
deviceOk = false;
|
||||
else if(type == null || type.trim().isEmpty())
|
||||
deviceOk = false;
|
||||
return deviceOk;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,355 @@
|
||||
package com.bwssystems.HABridge.plugins.broadlink;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.net.BindException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.BridgeSettings;
|
||||
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
|
||||
import com.bwssystems.HABridge.Configuration;
|
||||
import com.bwssystems.HABridge.Home;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.ColorDecode;
|
||||
import com.bwssystems.HABridge.hue.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
import com.github.mob41.blapi.BLDevice;
|
||||
import com.github.mob41.blapi.MP1Device;
|
||||
import com.github.mob41.blapi.SP1Device;
|
||||
import com.github.mob41.blapi.SP2Device;
|
||||
import com.github.mob41.blapi.mac.Mac;
|
||||
import com.github.mob41.blapi.mac.MacFormatException;
|
||||
import com.github.mob41.blapi.pkt.cmd.rm2.SendDataCmdPayload;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class BroadlinkHome implements Home {
|
||||
private static final Logger log = LoggerFactory.getLogger(BroadlinkHome.class);
|
||||
private Map<String, BLDevice> broadlinkMap;
|
||||
private Boolean validBroadlink;
|
||||
private boolean closed;
|
||||
private Boolean isDevMode;
|
||||
private BridgeSettingsDescriptor bridgeSettingsDesc;
|
||||
|
||||
public BroadlinkHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Home createHome(BridgeSettings bridgeSettings) {
|
||||
broadlinkMap = null;
|
||||
bridgeSettingsDesc = bridgeSettings.getBridgeSettingsDescriptor();
|
||||
validBroadlink = bridgeSettings.getBridgeSettingsDescriptor().isValidBroadlink();
|
||||
isDevMode = Boolean.parseBoolean(System.getProperty("dev.mode", "false"));
|
||||
if (isDevMode)
|
||||
validBroadlink = true;
|
||||
|
||||
if(validBroadlink)
|
||||
broadlinkDiscover();
|
||||
|
||||
log.info("Broadlink Home created." + (validBroadlink ? "" : " No Broadlinks configured.") + (isDevMode ? " DevMode is set." : ""));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItems(String type) {
|
||||
List<BroadlinkEntry> deviceList = new ArrayList<BroadlinkEntry>();
|
||||
if(!validBroadlink || broadlinkMap == null)
|
||||
return deviceList;
|
||||
BroadlinkEntry theResponse = null;
|
||||
log.debug("consolidating devices for Broadlink");
|
||||
Iterator<String> keys = broadlinkMap.keySet().iterator();
|
||||
while(keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
theResponse = toEntry(broadlinkMap.get(key));
|
||||
if(theResponse != null)
|
||||
deviceList.add(theResponse);
|
||||
else {
|
||||
log.warn("Cannot get BroadlinkDevice with name: " + key + ", skipping this Broadlink.");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
if(validBroadlink)
|
||||
broadlinkDiscover();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri, Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
String theReturn = null;
|
||||
boolean changeState = false;
|
||||
String theStringData = null;
|
||||
log.debug("executing HUE api request to send message to BroadlinkDevice: " + anItem.getItem().toString());
|
||||
if(!validBroadlink) {
|
||||
log.warn("Should not get here, no Broadlinks configured");
|
||||
theReturn = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||
+ "\",\"description\": \"Should not get here, no LifxDevices configured\", \"parameter\": \"/lights/"
|
||||
+ lightId + "state\"}}]";
|
||||
|
||||
} else {
|
||||
BroadlinkEntry broadlinkCommand = null;
|
||||
broadlinkCommand = new Gson().fromJson(anItem.getItem().getAsString(), BroadlinkEntry.class);
|
||||
BLDevice theDevice = null;
|
||||
if(broadlinkMap != null && !broadlinkMap.isEmpty())
|
||||
theDevice = broadlinkMap.get(broadlinkCommand.getId());
|
||||
|
||||
if (theDevice == null) {
|
||||
if(broadlinkCommand.hasIpAndMac()) {
|
||||
byte[] intBytes = DatatypeConverter.parseHexBinary(broadlinkCommand.getType());
|
||||
BigInteger theBig = new BigInteger(intBytes);
|
||||
int theType = theBig.intValue();
|
||||
try {
|
||||
theDevice = BLDevice.createInstance((short)theType, broadlinkCommand.getIpAddr(), new Mac(broadlinkCommand.getMacAddr()));
|
||||
} catch (MacFormatException e) {
|
||||
log.warn("Could not initialize BroadlinkDevice device due to Mac (" + broadlinkCommand.getId() + ") format exception: " + e.getMessage());
|
||||
theReturn = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||
+ "\",\"description\": \"Could not initialize BroadlinkDevice device due to Mac format exception\", \"parameter\": \"/lights/"
|
||||
+ lightId + "state\"}}]";
|
||||
} catch (IOException e) {
|
||||
log.warn("Could not initialize BroadlinkDevice device due to IP Address (" + broadlinkCommand.getId() + ") exception: " + e.getMessage());
|
||||
theReturn = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||
+ "\",\"description\": \"Could not initialize BroadlinkDevice device due to IP Address exception\", \"parameter\": \"/lights/"
|
||||
+ lightId + "state\"}}]";
|
||||
} catch (Exception e) {
|
||||
log.warn("Could not initialize BroadlinkDevice device due to (" + broadlinkCommand.getId() + ") exception: " + e.getMessage());
|
||||
theReturn = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||
+ "\",\"description\": \"Could not initialize BroadlinkDevice device due to exception\", \"parameter\": \"/lights/"
|
||||
+ lightId + "state\"}}]";
|
||||
}
|
||||
|
||||
if(broadlinkMap == null)
|
||||
broadlinkMap = new HashMap<String, BLDevice>();
|
||||
|
||||
String newId = theDevice.getHost() + "-" + String.format("%04x", theDevice.getDeviceType());
|
||||
if(broadlinkMap.get(newId) == null)
|
||||
broadlinkMap.put(newId, theDevice);
|
||||
}
|
||||
}
|
||||
if (theDevice == null) {
|
||||
log.warn("Should not get here, no BroadlinkDevice not available");
|
||||
theReturn = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||
+ "\",\"description\": \"Should not get here, no Broadlinks available\", \"parameter\": \"/lights/"
|
||||
+ lightId + "state\"}}]";
|
||||
} else {
|
||||
log.debug("calling BroadlinkDevice: " + broadlinkCommand.getName());
|
||||
try {
|
||||
if(!isDevMode) {
|
||||
if(!theDevice.auth()) {
|
||||
log.error("Call to " + broadlinkCommand.getId() + " device authorization failed.");
|
||||
theReturn = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||
+ "\",\"description\": \"" + broadlinkCommand.getId() + " device auth error.\", \"parameter\": \"/lights/"
|
||||
+ lightId + "state\"}}]";
|
||||
}
|
||||
}
|
||||
switch (theDevice.getDeviceType()) {
|
||||
case BLDevice.DEV_A1:
|
||||
log.debug("Broadlink A1 device called and not supported. No Action, device name = " + device.getName() + ", id= " + broadlinkCommand.getId());
|
||||
break;
|
||||
case BLDevice.DEV_MP1:
|
||||
if(broadlinkCommand.getCommand().equals("on"))
|
||||
changeState = true;
|
||||
else
|
||||
changeState = false;
|
||||
((MP1Device) theDevice).setState(Integer.parseInt(broadlinkCommand.getData()), changeState);
|
||||
break;
|
||||
case BLDevice.DEV_SP2:
|
||||
case BLDevice.DEV_SP2_HONEYWELL_ALT1:
|
||||
case BLDevice.DEV_SP2_HONEYWELL_ALT2:
|
||||
case BLDevice.DEV_SP2_HONEYWELL_ALT3:
|
||||
case BLDevice.DEV_SP2_HONEYWELL_ALT4:
|
||||
case BLDevice.DEV_SPMINI:
|
||||
case BLDevice.DEV_SP3:
|
||||
case BLDevice.DEV_SPMINI2:
|
||||
case BLDevice.DEV_SPMINI_OEM_ALT1:
|
||||
case BLDevice.DEV_SPMINI_OEM_ALT2:
|
||||
case BLDevice.DEV_SPMINI_PLUS:
|
||||
if(broadlinkCommand.getCommand().equals("on"))
|
||||
changeState = true;
|
||||
else
|
||||
changeState = false;
|
||||
((SP2Device) theDevice).setState(changeState);
|
||||
break;
|
||||
case BLDevice.DEV_SP1:
|
||||
if(broadlinkCommand.getCommand().equals("on"))
|
||||
changeState = true;
|
||||
else
|
||||
changeState = false;
|
||||
((SP1Device) theDevice).setPower(changeState);
|
||||
break;
|
||||
case BLDevice.DEV_RM_2:
|
||||
case BLDevice.DEV_RM_MINI:
|
||||
case BLDevice.DEV_RM_PRO_PHICOMM:
|
||||
case BLDevice.DEV_RM_2_HOME_PLUS:
|
||||
case BLDevice.DEV_RM_2_2HOME_PLUS_GDT:
|
||||
case BLDevice.DEV_RM_2_PRO_PLUS:
|
||||
case BLDevice.DEV_RM_2_PRO_PLUS_2:
|
||||
case BLDevice.DEV_RM_2_PRO_PLUS_2_BL:
|
||||
case BLDevice.DEV_RM_MINI_SHATE:
|
||||
if(broadlinkCommand.getData() != null && !broadlinkCommand.getData().trim().isEmpty()) {
|
||||
theStringData = broadlinkCommand.getData().trim();
|
||||
if(targetBri != null || targetBriInc != null) {
|
||||
theStringData = BrightnessDecode.calculateReplaceIntensityValue(theStringData, intensity, targetBri, targetBriInc, true);
|
||||
}
|
||||
if(colorData != null) {
|
||||
theStringData = ColorDecode.replaceColorData(theStringData, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), true);
|
||||
}
|
||||
theStringData = DeviceDataDecode.replaceDeviceData(theStringData, device);
|
||||
theStringData = TimeDecode.replaceTimeValue(theStringData);
|
||||
byte[] theData = DatatypeConverter.parseHexBinary(theStringData);
|
||||
SendDataCmdPayload thePayload = new SendDataCmdPayload(theData);
|
||||
|
||||
DatagramPacket thePacket = theDevice.sendCmdPkt(Configuration.BROADLINK_DISCONVER_TIMEOUT, thePayload);
|
||||
String returnData = null;
|
||||
if(thePacket != null)
|
||||
returnData = DatatypeConverter.printHexBinary(thePacket.getData());
|
||||
else
|
||||
returnData = "No Data - null";
|
||||
log.debug("RM2 Device data return: <<<" + returnData + ">>>");
|
||||
}
|
||||
else {
|
||||
log.error("Call to " + broadlinkCommand.getId() + " with no data, noop");
|
||||
theReturn = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||
+ "\",\"description\": \"" + broadlinkCommand.getId() + " could not call device without data.\", \"parameter\": \"/lights/"
|
||||
+ lightId + "state\"}}]";
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Call to " + broadlinkCommand.getId() + " device failed with exception: " + e.getMessage(), e);
|
||||
theReturn = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||
+ "\",\"description\": \"" + broadlinkCommand.getId() + " device call error.\", \"parameter\": \"/lights/"
|
||||
+ lightId + "state\"}}]";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return theReturn;
|
||||
}
|
||||
|
||||
private BroadlinkEntry toEntry(BLDevice broadlinkObject) {
|
||||
short baseType = 0;
|
||||
switch (broadlinkObject.getDeviceType()) {
|
||||
case BLDevice.DEV_MP1:
|
||||
baseType = BLDevice.DEV_MP1;
|
||||
break;
|
||||
case BLDevice.DEV_SP2:
|
||||
case BLDevice.DEV_SP2_HONEYWELL_ALT1:
|
||||
case BLDevice.DEV_SP2_HONEYWELL_ALT2:
|
||||
case BLDevice.DEV_SP2_HONEYWELL_ALT3:
|
||||
case BLDevice.DEV_SP2_HONEYWELL_ALT4:
|
||||
case BLDevice.DEV_SPMINI:
|
||||
case BLDevice.DEV_SP3:
|
||||
case BLDevice.DEV_SPMINI2:
|
||||
case BLDevice.DEV_SPMINI_OEM_ALT1:
|
||||
case BLDevice.DEV_SPMINI_OEM_ALT2:
|
||||
case BLDevice.DEV_SPMINI_PLUS:
|
||||
baseType = BLDevice.DEV_SP2;
|
||||
break;
|
||||
case BLDevice.DEV_SP1:
|
||||
baseType = BLDevice.DEV_SP1;
|
||||
break;
|
||||
case BLDevice.DEV_RM_2:
|
||||
case BLDevice.DEV_RM_MINI:
|
||||
case BLDevice.DEV_RM_PRO_PHICOMM:
|
||||
case BLDevice.DEV_RM_2_HOME_PLUS:
|
||||
case BLDevice.DEV_RM_2_2HOME_PLUS_GDT:
|
||||
case BLDevice.DEV_RM_2_PRO_PLUS:
|
||||
case BLDevice.DEV_RM_2_PRO_PLUS_2:
|
||||
case BLDevice.DEV_RM_2_PRO_PLUS_2_BL:
|
||||
case BLDevice.DEV_RM_MINI_SHATE:
|
||||
baseType = BLDevice.DEV_RM_2;
|
||||
break;
|
||||
}
|
||||
BroadlinkEntry anEntry = new BroadlinkEntry();
|
||||
anEntry.setId(broadlinkObject.getHost() + "-" + String.format("%04x", broadlinkObject.getDeviceType()));
|
||||
anEntry.setName(broadlinkObject.getDeviceDescription());
|
||||
anEntry.setType(String.format("%04x", broadlinkObject.getDeviceType()));
|
||||
anEntry.setBaseType(String.format("%04x", baseType));
|
||||
anEntry.setDesc(BLDevice.getDescOfType(broadlinkObject.getDeviceType()));
|
||||
anEntry.setIpAddr(broadlinkObject.getHost());
|
||||
anEntry.setMacAddr(broadlinkObject.getMac().getMacString());
|
||||
return anEntry;
|
||||
}
|
||||
|
||||
public BLDevice[] broadlinkDiscover () {
|
||||
BLDevice[] clients = null;
|
||||
int aDiscoverPort = Configuration.BROADLINK_DISCOVER_PORT;
|
||||
broadlinkMap = new HashMap<String, BLDevice>();
|
||||
while(aDiscoverPort > 0) {
|
||||
try {
|
||||
log.info("Broadlink discover....");
|
||||
if(isDevMode) {
|
||||
clients = TestBLDevice.discoverDevices(InetAddress.getByName(bridgeSettingsDesc.getUpnpConfigAddress()), aDiscoverPort, Configuration.BROADLINK_DISCONVER_TIMEOUT);
|
||||
}
|
||||
else
|
||||
clients = BLDevice.discoverDevices(InetAddress.getByName(bridgeSettingsDesc.getUpnpConfigAddress()), aDiscoverPort, Configuration.BROADLINK_DISCONVER_TIMEOUT);
|
||||
for(int i = 0; i < clients.length; i++) {
|
||||
if(clients[i].getDeviceType() != BLDevice.DEV_A1 && broadlinkMap.get(clients[i].getHost() + "-" + String.format("%04x", clients[i].getDeviceType())) == null) {
|
||||
broadlinkMap.put(clients[i].getHost() + "-" + String.format("%04x", clients[i].getDeviceType()), clients[i]);
|
||||
log.debug("Adding Device to Map - host: " + clients[i].getHost() + ", device Type: " + clients[i].getDeviceDescription() + ", mac: " + (clients[i].getMac() == null ? "no Mac in client" : clients[i].getMac().getMacString()));
|
||||
} else {
|
||||
log.debug("Ignoring Device (already in the list or an A1 Device) - host: " + clients[i].getHost() + ", device Type: " + clients[i].getDeviceDescription() + ", mac: " + (clients[i].getMac() == null ? "no Mac in client" : clients[i].getMac().getMacString()));
|
||||
}
|
||||
}
|
||||
aDiscoverPort = 0;
|
||||
} catch (BindException e) {
|
||||
log.warn("Could not discover Broadlinks, Port in use, increasing by 11");
|
||||
aDiscoverPort += 11;
|
||||
if(aDiscoverPort > Configuration.BROADLINK_DISCOVER_PORT + 110)
|
||||
aDiscoverPort = 0;
|
||||
} catch (IOException e) {
|
||||
log.warn("Could not discover Broadlinks, with IO Exception", e);
|
||||
broadlinkMap = null;
|
||||
aDiscoverPort = 0;
|
||||
}
|
||||
}
|
||||
if(clients == null || clients.length <= 0) {
|
||||
log.warn("Did not discover any Broadlinks.");
|
||||
broadlinkMap = null;
|
||||
} else {
|
||||
log.info("Broadlink discover found " + clients.length + " clients.");
|
||||
}
|
||||
return clients;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
if(!validBroadlink)
|
||||
return;
|
||||
log.debug("Closing Home.");
|
||||
if(broadlinkMap != null) {
|
||||
broadlinkMap.clear();
|
||||
broadlinkMap = null;
|
||||
}
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.bwssystems.HABridge.plugins.broadlink;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.InetAddress;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.github.mob41.blapi.BLDevice;
|
||||
import com.github.mob41.blapi.mac.Mac;
|
||||
import com.github.mob41.blapi.pkt.CmdPayload;
|
||||
|
||||
public class TestBLDevice extends BLDevice {
|
||||
private static final Logger log = LoggerFactory.getLogger(TestBLDevice.class);
|
||||
|
||||
protected TestBLDevice(short deviceType, String deviceDesc, String host, Mac mac) throws IOException {
|
||||
super(deviceType, deviceDesc, host, mac);
|
||||
}
|
||||
|
||||
public void setState(boolean aState) {
|
||||
log.info("setState called with " + aState);
|
||||
}
|
||||
|
||||
public void setState(int anIndex, boolean aState) {
|
||||
log.info("setState called with index " + anIndex + " and state " + aState);
|
||||
}
|
||||
|
||||
public void setPower(boolean aState) {
|
||||
log.info("setPower called with " + aState);
|
||||
}
|
||||
|
||||
public DatagramPacket sendCmdPkt(int timeout, CmdPayload aCmd) {
|
||||
log.info("sendCmdPkt called with " + DatatypeConverter.printHexBinary(aCmd.getPayload().getData()));
|
||||
return null;
|
||||
}
|
||||
|
||||
public static BLDevice[] discoverDevices(InetAddress theAddress, int aport, int timeout) {
|
||||
TestMP1Device mp1Device = null;
|
||||
TestSP1Device sp1Device = null;
|
||||
TestSP2Device sp2Device = null;
|
||||
TestRM2Device rm2Device = null;
|
||||
try {
|
||||
mp1Device = new TestMP1Device("mp1host", null);
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
sp1Device = new TestSP1Device("sp1host", null);
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
sp2Device = new TestSP2Device("sp2host", null);
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
rm2Device = new TestRM2Device("rm2host", null);
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
BLDevice[] devices = { mp1Device, sp1Device, sp2Device, rm2Device };
|
||||
log.info("Created test devices");
|
||||
return devices;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.bwssystems.HABridge.plugins.broadlink;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.github.mob41.blapi.MP1Device;
|
||||
import com.github.mob41.blapi.mac.Mac;
|
||||
import com.github.mob41.blapi.pkt.CmdPayload;
|
||||
|
||||
public class TestMP1Device extends MP1Device {
|
||||
private static final Logger log = LoggerFactory.getLogger(TestMP1Device.class);
|
||||
|
||||
protected TestMP1Device(String host, Mac mac) throws IOException {
|
||||
super(host, mac);
|
||||
}
|
||||
|
||||
public void setState(int anIndex, boolean aState) {
|
||||
log.info("setState called with index " + anIndex + " and state " + aState);
|
||||
}
|
||||
|
||||
public DatagramPacket sendCmdPkt(int timeout, CmdPayload aCmd) {
|
||||
log.info("sendCmdPkt called with " + DatatypeConverter.printHexBinary(aCmd.getPayload().getData()));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.bwssystems.HABridge.plugins.broadlink;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.github.mob41.blapi.RM2Device;
|
||||
import com.github.mob41.blapi.mac.Mac;
|
||||
import com.github.mob41.blapi.pkt.CmdPayload;
|
||||
import com.github.mob41.blapi.pkt.cmd.rm2.SendDataCmdPayload;
|
||||
|
||||
public class TestRM2Device extends RM2Device {
|
||||
private static final Logger log = LoggerFactory.getLogger(TestRM2Device.class);
|
||||
|
||||
protected TestRM2Device(String host, Mac mac) throws IOException {
|
||||
super(host, mac);
|
||||
}
|
||||
|
||||
public DatagramPacket sendCmdPkt(int timeout, CmdPayload aCmd) {
|
||||
log.info("sendCmdPkt called with " + DatatypeConverter.printHexBinary(((SendDataCmdPayload)aCmd).getData()));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.bwssystems.HABridge.plugins.broadlink;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.github.mob41.blapi.SP1Device;
|
||||
import com.github.mob41.blapi.mac.Mac;
|
||||
import com.github.mob41.blapi.pkt.CmdPayload;
|
||||
|
||||
public class TestSP1Device extends SP1Device {
|
||||
private static final Logger log = LoggerFactory.getLogger(TestSP1Device.class);
|
||||
|
||||
protected TestSP1Device(String host, Mac mac) throws IOException {
|
||||
super(host, mac);
|
||||
}
|
||||
|
||||
public void setPower(boolean aState) {
|
||||
log.info("setPower called with " + aState);
|
||||
}
|
||||
|
||||
public DatagramPacket sendCmdPkt(int timeout, CmdPayload aCmd) {
|
||||
log.info("sendCmdPkt called with " + DatatypeConverter.printHexBinary(aCmd.getPayload().getData()));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.bwssystems.HABridge.plugins.broadlink;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.github.mob41.blapi.SP2Device;
|
||||
import com.github.mob41.blapi.mac.Mac;
|
||||
import com.github.mob41.blapi.pkt.CmdPayload;
|
||||
|
||||
public class TestSP2Device extends SP2Device {
|
||||
private static final Logger log = LoggerFactory.getLogger(TestSP2Device.class);
|
||||
|
||||
protected TestSP2Device(String host, Mac mac) throws IOException {
|
||||
super(host, mac);
|
||||
}
|
||||
|
||||
public void setState(boolean aState) {
|
||||
log.info("setState called with " + aState);
|
||||
}
|
||||
|
||||
public DatagramPacket sendCmdPkt(int timeout, CmdPayload aCmd) {
|
||||
log.info("sendCmdPkt called with " + DatatypeConverter.printHexBinary(aCmd.getPayload().getData()));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,13 @@ import com.bwssystems.HABridge.api.hue.HueError;
|
||||
import com.bwssystems.HABridge.api.hue.HueErrorResponse;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.ColorDecode;
|
||||
import com.bwssystems.HABridge.hue.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHome;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class DomoticzHome implements Home {
|
||||
@@ -26,17 +31,20 @@ public class DomoticzHome implements Home {
|
||||
private Map<String, DomoticzHandler> domoticzs;
|
||||
private Boolean validDomoticz;
|
||||
private HTTPHandler httpClient;
|
||||
private boolean closed;
|
||||
|
||||
public DomoticzHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItems(String type) {
|
||||
if(!validDomoticz)
|
||||
return null;
|
||||
log.debug("consolidating devices for hues");
|
||||
log.debug("consolidating devices for Domoticzs");
|
||||
List<DomoticzDevice> theResponse = null;
|
||||
Iterator<String> keys = domoticzs.keySet().iterator();
|
||||
List<DomoticzDevice> deviceList = new ArrayList<DomoticzDevice>();
|
||||
@@ -58,6 +66,11 @@ public class DomoticzHome implements Home {
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
// noop
|
||||
}
|
||||
|
||||
private Boolean addDomoticzDevices(List<DomoticzDevice> theDeviceList, List<DomoticzDevice> theSourceList, String theKey) {
|
||||
if(!validDomoticz)
|
||||
return null;
|
||||
@@ -71,7 +84,7 @@ public class DomoticzHome implements Home {
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
Devices theDomoticzApiResponse = null;
|
||||
String responseString = null;
|
||||
|
||||
@@ -90,7 +103,23 @@ public class DomoticzHome implements Home {
|
||||
String theData;
|
||||
String anUrl = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody,
|
||||
intensity, targetBri, targetBriInc, false);
|
||||
theData = httpClient.doHttpRequest(theHandler.buildUrl(anUrl), null, null, null, theHandler.buildHeaders());
|
||||
if (colorData != null) {
|
||||
anUrl = ColorDecode.replaceColorData(anUrl, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false);
|
||||
}
|
||||
anUrl = DeviceDataDecode.replaceDeviceData(anUrl, device);
|
||||
anUrl = TimeDecode.replaceTimeValue(anUrl);
|
||||
|
||||
String aBody = null;
|
||||
if(anItem.getHttpBody()!= null && !anItem.getHttpBody().isEmpty()) {
|
||||
aBody = BrightnessDecode.calculateReplaceIntensityValue(anItem.getHttpBody(),
|
||||
intensity, targetBri, targetBriInc, false);
|
||||
if (colorData != null) {
|
||||
aBody = ColorDecode.replaceColorData(aBody, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false);
|
||||
}
|
||||
aBody = DeviceDataDecode.replaceDeviceData(aBody, device);
|
||||
aBody = TimeDecode.replaceTimeValue(aBody);
|
||||
}
|
||||
theData = httpClient.doHttpRequest(theHandler.buildUrl(anUrl), null, null, aBody, theHandler.buildHeaders());
|
||||
try {
|
||||
theDomoticzApiResponse = new Gson().fromJson(theData, Devices.class);
|
||||
if(theDomoticzApiResponse.getStatus().equals("OK"))
|
||||
@@ -128,7 +157,7 @@ public class DomoticzHome implements Home {
|
||||
log.info("Domoticz Home created." + (validDomoticz ? "" : " No Domoticz devices configured."));
|
||||
if(!validDomoticz)
|
||||
return null;
|
||||
httpClient = new HTTPHandler();
|
||||
httpClient = HTTPHome.getHandler();
|
||||
domoticzs = new HashMap<String, DomoticzHandler>();
|
||||
Iterator<NamedIP> theList = bridgeSettings.getBridgeSettingsDescriptor().getDomoticzaddress().getDevices().iterator();
|
||||
while(theList.hasNext()) {
|
||||
@@ -161,8 +190,16 @@ public class DomoticzHome implements Home {
|
||||
}
|
||||
@Override
|
||||
public void closeHome() {
|
||||
log.debug("Closing Home.");
|
||||
if(closed || !validDomoticz) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
|
||||
if(httpClient != null)
|
||||
httpClient.closeHandler();
|
||||
|
||||
|
||||
domoticzs = null;
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.bwssystems.HABridge.plugins.exec;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -10,36 +11,42 @@ import com.bwssystems.HABridge.Home;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.ColorDecode;
|
||||
import com.bwssystems.HABridge.hue.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
|
||||
public class CommandHome implements Home {
|
||||
private static final Logger log = LoggerFactory.getLogger(CommandHome.class);
|
||||
private String execGarden;;
|
||||
private BridgeSettings theSettings;
|
||||
private boolean closed;
|
||||
|
||||
public CommandHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int itensity, Integer targetBri, Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
log.debug("Exec Request called with url: " + anItem.getItem().getAsString());
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity, Integer targetBri, Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
log.debug("Exec Request called with url: " + anItem.getItem().getAsString() + " and exec Garden: " + (theSettings.getBridgeSecurity().getExecGarden() == null ? "not given" : theSettings.getBridgeSecurity().getExecGarden()));
|
||||
String responseString = null;
|
||||
String intermediate;
|
||||
if (anItem.getItem().getAsString().contains("exec://"))
|
||||
intermediate = anItem.getItem().getAsString().substring(anItem.getItem().getAsString().indexOf("://") + 3);
|
||||
else
|
||||
intermediate = anItem.getItem().getAsString();
|
||||
intermediate = BrightnessDecode.calculateReplaceIntensityValue(intermediate, itensity, targetBri, targetBriInc, false);
|
||||
intermediate = BrightnessDecode.calculateReplaceIntensityValue(intermediate, intensity, targetBri, targetBriInc, false);
|
||||
if (colorData != null) {
|
||||
intermediate = ColorDecode.replaceColorData(intermediate, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false);
|
||||
}
|
||||
intermediate = DeviceDataDecode.replaceDeviceData(intermediate, device);
|
||||
intermediate = TimeDecode.replaceTimeValue(intermediate);
|
||||
if(execGarden != null) {
|
||||
if(System.getProperty("os.name").toLowerCase().indexOf("win") > 0)
|
||||
intermediate = execGarden + "\\" + intermediate;
|
||||
else
|
||||
intermediate = execGarden + "/" + intermediate;
|
||||
String execGarden = theSettings.getBridgeSecurity().getExecGarden();
|
||||
if(execGarden != null && !execGarden.trim().isEmpty()) {
|
||||
intermediate = new File(execGarden.trim(), intermediate).getAbsolutePath();
|
||||
}
|
||||
|
||||
String anError = doExecRequest(intermediate, lightId);
|
||||
@@ -57,7 +64,7 @@ public class CommandHome implements Home {
|
||||
Process p = Runtime.getRuntime().exec(anItem);
|
||||
log.debug("Process running: " + p.isAlive());
|
||||
} catch (IOException e) {
|
||||
log.warn("Could not execute request: " + anItem, e);
|
||||
log.warn("Could not execute request: " + anItem + " with message: " + e.getMessage());
|
||||
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||
+ "\",\"description\": \"Error on calling out to device\", \"parameter\": \"/lights/" + lightId
|
||||
+ "state\"}}]";
|
||||
@@ -75,7 +82,7 @@ public class CommandHome implements Home {
|
||||
@Override
|
||||
public Home createHome(BridgeSettings bridgeSettings) {
|
||||
log.info("Command Home for system program execution created.");
|
||||
this.execGarden = bridgeSettings.getBridgeSecurity().getExecGarden();
|
||||
this.theSettings = bridgeSettings;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -85,10 +92,20 @@ public class CommandHome implements Home {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
// noop
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
|
||||
closed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.bwssystems.HABridge.plugins.fhem;
|
||||
|
||||
public class FHEMCommand {
|
||||
private String url;
|
||||
private String command;
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
public void setCommand(String command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.bwssystems.HABridge.plugins.fhem;
|
||||
|
||||
public class FHEMDevice {
|
||||
|
||||
private String address;
|
||||
private String name;
|
||||
private Result item;
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public Result getItem() {
|
||||
return item;
|
||||
}
|
||||
public void setItem(Result item) {
|
||||
this.item = item;
|
||||
}
|
||||
}
|
||||
213
src/main/java/com/bwssystems/HABridge/plugins/fhem/FHEMHome.java
Normal file
213
src/main/java/com/bwssystems/HABridge/plugins/fhem/FHEMHome.java
Normal file
@@ -0,0 +1,213 @@
|
||||
package com.bwssystems.HABridge.plugins.fhem;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.BridgeSettings;
|
||||
import com.bwssystems.HABridge.DeviceMapTypes;
|
||||
import com.bwssystems.HABridge.Home;
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.api.hue.HueError;
|
||||
import com.bwssystems.HABridge.api.hue.HueErrorResponse;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.ColorDecode;
|
||||
import com.bwssystems.HABridge.hue.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHome;
|
||||
import com.bwssystems.HABridge.plugins.http.HttpTestHandler;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class FHEMHome implements Home {
|
||||
private static final Logger log = LoggerFactory.getLogger(FHEMHome.class);
|
||||
private Map<String, FHEMInstance> fhemMap;
|
||||
private Boolean validFhem;
|
||||
private Boolean isDevMode;
|
||||
private HTTPHandler httpClient;
|
||||
private boolean closed;
|
||||
|
||||
public FHEMHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri, Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
|
||||
String theUrl = anItem.getItem().getAsString();
|
||||
String responseString = null;
|
||||
|
||||
if(theUrl != null && !theUrl.isEmpty()) {
|
||||
FHEMCommand theCommand = null;
|
||||
try {
|
||||
theCommand = new Gson().fromJson(theUrl, FHEMCommand.class);
|
||||
} catch(Exception e) {
|
||||
log.warn("Cannot parse command to FHEM <<<" + theUrl + ">>>", e);
|
||||
responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId,
|
||||
"Error on calling url to change device state", "/lights/"
|
||||
+ lightId + "state", null, null).getTheErrors(), HueError[].class);
|
||||
return responseString;
|
||||
}
|
||||
String intermediate = theCommand.getUrl().substring(theCommand.getUrl().indexOf("://") + 3);
|
||||
String hostPortion = intermediate.substring(0, intermediate.indexOf('/'));
|
||||
String theUrlBody = intermediate.substring(intermediate.indexOf('/') + 1);
|
||||
String hostAddr = null;
|
||||
if (hostPortion.contains(":")) {
|
||||
hostAddr = hostPortion.substring(0, intermediate.indexOf(':'));
|
||||
} else
|
||||
hostAddr = hostPortion;
|
||||
FHEMInstance theHandler = findHandlerByAddress(hostAddr);
|
||||
if(theHandler != null) {
|
||||
String anUrl = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody,
|
||||
intensity, targetBri, targetBriInc, false);
|
||||
if (colorData != null) {
|
||||
anUrl = ColorDecode.replaceColorData(anUrl, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false);
|
||||
}
|
||||
anUrl = DeviceDataDecode.replaceDeviceData(anUrl, device);
|
||||
anUrl = TimeDecode.replaceTimeValue(anUrl);
|
||||
|
||||
String aCommand = null;
|
||||
if(theCommand.getCommand() != null && !theCommand.getCommand().isEmpty()) {
|
||||
aCommand = BrightnessDecode.calculateReplaceIntensityValue(theCommand.getCommand(),
|
||||
intensity, targetBri, targetBriInc, false);
|
||||
if (colorData != null) {
|
||||
aCommand = ColorDecode.replaceColorData(aCommand, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false);
|
||||
}
|
||||
aCommand = DeviceDataDecode.replaceDeviceData(aCommand, device);
|
||||
aCommand = TimeDecode.replaceTimeValue(aCommand);
|
||||
}
|
||||
try {
|
||||
theHandler.callCommand(anUrl, aCommand, httpClient);
|
||||
} catch (Exception e) {
|
||||
log.warn("Cannot send comand to FHEM", e);
|
||||
responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId,
|
||||
"Error on calling url to change device state", "/lights/"
|
||||
+ lightId + "state", null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
} else {
|
||||
log.warn("FHEM Call could not complete, no address found: " + theUrl);
|
||||
responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId,
|
||||
"Error on calling url to change device state", "/lights/"
|
||||
+ lightId + "state", null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
} else {
|
||||
log.warn("FHEM Call to be presented as http(s)://<ip_address>(:<port>)/payload, format of request unknown: " + theUrl);
|
||||
responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId,
|
||||
"Error on calling url to change device state", "/lights/"
|
||||
+ lightId + "state", null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
return responseString;
|
||||
}
|
||||
|
||||
private FHEMInstance findHandlerByAddress(String hostAddress) {
|
||||
FHEMInstance aHandler = null;
|
||||
boolean found = false;
|
||||
Iterator<String> keys = fhemMap.keySet().iterator();
|
||||
while(keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
aHandler = fhemMap.get(key);
|
||||
if(aHandler != null && aHandler.getFhemAddress().getIp().equals(hostAddress)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
aHandler = null;
|
||||
return aHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItems(String type) {
|
||||
|
||||
if(!validFhem)
|
||||
return null;
|
||||
log.debug("consolidating devices for FHEM");
|
||||
List<FHEMDevice> theResponse = null;
|
||||
Iterator<String> keys = fhemMap.keySet().iterator();
|
||||
List<FHEMDevice> deviceList = new ArrayList<FHEMDevice>();
|
||||
while(keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
theResponse = fhemMap.get(key).getDevices(httpClient);
|
||||
if(theResponse != null)
|
||||
addFHEMDevices(deviceList, theResponse, key);
|
||||
else {
|
||||
log.warn("Cannot get devices for FHEM: " + key + ", skipping this FHEM.");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
// noop
|
||||
}
|
||||
|
||||
private Boolean addFHEMDevices(List<FHEMDevice> theDeviceList, List<FHEMDevice> theSourceList, String theKey) {
|
||||
Iterator<FHEMDevice> devices = theSourceList.iterator();
|
||||
while(devices.hasNext()) {
|
||||
FHEMDevice theDevice = devices.next();
|
||||
theDeviceList.add(theDevice);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Home createHome(BridgeSettings bridgeSettings) {
|
||||
isDevMode = Boolean.parseBoolean(System.getProperty("dev.mode", "false"));
|
||||
fhemMap = null;
|
||||
validFhem = bridgeSettings.getBridgeSettingsDescriptor().isValidFhem();
|
||||
log.info("FHEM Home created." + (validFhem ? "" : " No FHEMs configured.") + (isDevMode ? " DevMode is set." : ""));
|
||||
if(validFhem) {
|
||||
fhemMap = new HashMap<String,FHEMInstance>();
|
||||
httpClient = HTTPHome.getHandler();
|
||||
if(isDevMode) {
|
||||
httpClient = new HttpTestHandler();
|
||||
((HttpTestHandler)httpClient).setTheData("cmd=jsonlist2", FHEMTestData.TestData);
|
||||
((HttpTestHandler)httpClient).setTheData("set", "FHEM Command Received");
|
||||
((HttpTestHandler)httpClient).setTheData(null, "FHEM no match");
|
||||
}
|
||||
httpClient.setCallType(DeviceMapTypes.FHEM_DEVICE[DeviceMapTypes.typeIndex]);
|
||||
Iterator<NamedIP> theList = bridgeSettings.getBridgeSettingsDescriptor().getFhemaddress().getDevices().iterator();
|
||||
while(theList.hasNext() && validFhem) {
|
||||
NamedIP aFhem = theList.next();
|
||||
try {
|
||||
fhemMap.put(aFhem.getName(), new FHEMInstance(aFhem));
|
||||
} catch (Exception e) {
|
||||
log.error("Cannot get FHEM (" + aFhem.getName() + ") setup, Exiting with message: " + e.getMessage(), e);
|
||||
validFhem = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
log.debug("Closing Home.");
|
||||
if(!closed && validFhem) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
|
||||
if(httpClient != null)
|
||||
httpClient.closeHandler();
|
||||
|
||||
fhemMap = null;
|
||||
closed = true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.bwssystems.HABridge.plugins.fhem;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.NameValue;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class FHEMInstance {
|
||||
private static final Logger log = LoggerFactory.getLogger(FHEMInstance.class);
|
||||
private NamedIP theFhem;
|
||||
|
||||
public FHEMInstance(NamedIP fhemLocation) {
|
||||
super();
|
||||
theFhem = fhemLocation;
|
||||
}
|
||||
|
||||
public NamedIP getFhemAddress() {
|
||||
return theFhem;
|
||||
}
|
||||
|
||||
public void setFhemAddress(NamedIP fhemAddress) {
|
||||
this.theFhem = fhemAddress;
|
||||
}
|
||||
|
||||
public Boolean callCommand(String aCommand, String commandData, HTTPHandler httpClient) {
|
||||
String aUrl = null;
|
||||
NameValue[] headers = null;
|
||||
if(theFhem.getSecure() != null && theFhem.getSecure())
|
||||
aUrl = "https://";
|
||||
else
|
||||
aUrl = "http://";
|
||||
if(theFhem.getUsername() != null && !theFhem.getUsername().isEmpty() && theFhem.getPassword() != null && !theFhem.getPassword().isEmpty()) {
|
||||
aUrl = aUrl + theFhem.getUsername() + ":" + theFhem.getPassword() + "@";
|
||||
}
|
||||
aUrl = aUrl + theFhem.getIp() + ":" + theFhem.getPort() + "/" + aCommand + commandData;
|
||||
log.debug("calling FHEM: " + aUrl);
|
||||
String theData = httpClient.doHttpRequest(aUrl, HttpPost.METHOD_NAME, "text/plain", null, headers);
|
||||
if(theData != null)
|
||||
log.debug("doHttpRequest returned data: <" + theData + ">");
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<FHEMDevice> getDevices(HTTPHandler httpClient) {
|
||||
List<FHEMDevice> deviceList = null;
|
||||
FHEMItem theFhemStates;
|
||||
String theUrl = null;
|
||||
String theData;
|
||||
NameValue[] headers = null;
|
||||
if(theFhem.getSecure() != null && theFhem.getSecure())
|
||||
theUrl = "https://";
|
||||
else
|
||||
theUrl = "http://";
|
||||
if(theFhem.getUsername() != null && !theFhem.getUsername().isEmpty() && theFhem.getPassword() != null && !theFhem.getPassword().isEmpty()) {
|
||||
theUrl = theUrl + theFhem.getUsername() + ":" + theFhem.getPassword() + "@";
|
||||
}
|
||||
theUrl = theUrl + theFhem.getIp() + ":" + theFhem.getPort() + "/fhem?cmd=jsonlist2";
|
||||
if(theFhem.getWebhook() != null && !theFhem.getWebhook().trim().isEmpty())
|
||||
theUrl = theUrl + "%20room=" + theFhem.getWebhook().trim();
|
||||
theData = httpClient.doHttpRequest(theUrl, HttpGet.METHOD_NAME, "application/json", null, headers);
|
||||
if(theData != null) {
|
||||
log.debug("GET FHEM States - data: " + theData);
|
||||
theData = getJSONData(theData);
|
||||
theFhemStates = new Gson().fromJson(theData, FHEMItem.class);
|
||||
if(theFhemStates == null) {
|
||||
log.warn("Cannot get any devices for FHEM " + theFhem.getName() + " as response is not parsable.");
|
||||
}
|
||||
else {
|
||||
deviceList = new ArrayList<FHEMDevice>();
|
||||
|
||||
for (Result aResult:theFhemStates.getResults()) {
|
||||
String name = aResult.getName();
|
||||
if(name.contains("<a href=")) {
|
||||
name = name.substring(name.indexOf("<a href=") + name.indexOf(">"));
|
||||
name = name.substring(1, name.indexOf("</a"));
|
||||
aResult.setName(name);
|
||||
}
|
||||
FHEMDevice aNewFhemDeviceDevice = new FHEMDevice();
|
||||
aNewFhemDeviceDevice.setItem(aResult);
|
||||
aNewFhemDeviceDevice.setAddress(theFhem.getIp() + ":" + theFhem.getPort());
|
||||
aNewFhemDeviceDevice.setName(theFhem.getName());
|
||||
deviceList.add(aNewFhemDeviceDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
log.warn("Cannot get an devices for FHEM " + theFhem.getName() + " http call failed.");
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
public String getJSONData(String response) {
|
||||
String theData;
|
||||
theData = response.substring(response.indexOf("<pre>") + 4);
|
||||
theData = theData.substring(1, theData.indexOf("</pre>") - 1);
|
||||
theData = theData.replace("\n", "");
|
||||
theData = theData.replace("\r", "");
|
||||
theData = theData.replace("<a href=\"", "<a href=\\\"");
|
||||
theData = theData.replace("\">", "\\\">");
|
||||
return theData;
|
||||
}
|
||||
|
||||
protected void closeClient() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
package com.bwssystems.HABridge.plugins.fhem;
|
||||
|
||||
import java.util.List;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class FHEMItem {
|
||||
|
||||
@SerializedName("Arg")
|
||||
@Expose
|
||||
private String arg;
|
||||
@SerializedName("Results")
|
||||
@Expose
|
||||
private List<Result> results = null;
|
||||
@SerializedName("totalResultsReturned")
|
||||
@Expose
|
||||
private Integer totalResultsReturned;
|
||||
|
||||
public String getArg() {
|
||||
return arg;
|
||||
}
|
||||
|
||||
public void setArg(String arg) {
|
||||
this.arg = arg;
|
||||
}
|
||||
|
||||
public List<Result> getResults() {
|
||||
return results;
|
||||
}
|
||||
|
||||
public void setResults(List<Result> results) {
|
||||
this.results = results;
|
||||
}
|
||||
|
||||
public Integer getTotalResultsReturned() {
|
||||
return totalResultsReturned;
|
||||
}
|
||||
|
||||
public void setTotalResultsReturned(Integer totalResultsReturned) {
|
||||
this.totalResultsReturned = totalResultsReturned;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
package com.bwssystems.HABridge.plugins.fhem;
|
||||
|
||||
public class FHEMTestData {
|
||||
public final static String TestData = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" +
|
||||
"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" +
|
||||
" <head root=\"/fhem\">\n" +
|
||||
" <title>Home, Sweet Home</title>\n" +
|
||||
" <link rel=\"shortcut icon\" href=\"/fhem/icons/favicon\" />\n" +
|
||||
" <meta charset=\"UTF-8\">\n" +
|
||||
" <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n" +
|
||||
" <link href=\"/fhem/pgm2/style.css?v=1513026539\" rel=\"stylesheet\"/>\n" +
|
||||
" <link href=\"/fhem/pgm2/jquery-ui.min.css\" rel=\"stylesheet\"/>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/jquery.min.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/jquery-ui.min.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb_colorpicker.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb_fbcalllist.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb_knob.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb_readingsGroup.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb_readingsHistory.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb_sortable.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb_uzsu.js\"></script>\n" +
|
||||
" <script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb_weekprofile.js\"></script>\n" +
|
||||
" </head>\n" +
|
||||
" <body name='Home, Sweet Home' fw_id='7880' generated=\"1513272732\" longpoll=\"1\" data-confirmDelete='1' data-confirmJSError='1' data-webName='haBridgeWeb '>\n" +
|
||||
" <div id=\"menuScrollArea\">\n" +
|
||||
" <div>\n" +
|
||||
" <a href=\"/fhem?\">\n" +
|
||||
" <div id=\"logo\"></div>\n" +
|
||||
" </a>\n" +
|
||||
" </div>\n" +
|
||||
" <div id=\"menu\">\n" +
|
||||
" <table>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <table class=\"room roomBlock1\">\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_Save_config\">\n" +
|
||||
" <a href=\"/fhem?cmd=save\">Save config</a>\n" +
|
||||
" <a id=\"saveCheck\" class=\"changed\" style=\"visibility:visible\">?</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" </table>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <table class=\"room roomBlock2\">\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_Alexa\">\n" +
|
||||
" <a href=\"/fhem?room=Alexa\">Alexa</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_System\">\n" +
|
||||
" <a href=\"/fhem?room=System\">System</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_WG_Zimmer\">\n" +
|
||||
" <a href=\"/fhem?room=WG%2dZimmer\">WG-Zimmer</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_habridge\">\n" +
|
||||
" <a href=\"/fhem?room=habridge\">habridge</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_Everything\">\n" +
|
||||
" <a href=\"/fhem?room=all\">\n" +
|
||||
" <img class='icon icoEverything' src=\"/fhem/images/default/icoEverything.png\" alt=\"icoEverything\" title=\"icoEverything\"> Everything\n" +
|
||||
" </a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" </table>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <table class=\"room roomBlock3\">\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_Logfile\">\n" +
|
||||
" <a href=\"/fhem/FileLog_logWrapper?dev=Logfile&type=text&file=fhem-2017-12.log\">Logfile</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div>\n" +
|
||||
" <a href=\"/fhem/docs/commandref.html\" target=\"_blank\" >Commandref</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div>\n" +
|
||||
" <a href=\"http://fhem.de/fhem.html#Documentation\" target=\"_blank\" >Remote doc</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_Edit_files\">\n" +
|
||||
" <a href=\"/fhem?cmd=style%20list\">Edit files</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_Select_style\">\n" +
|
||||
" <a href=\"/fhem?cmd=style%20select\">Select style</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>\n" +
|
||||
" <div class=\"menu_Event_monitor\">\n" +
|
||||
" <a href=\"/fhem?cmd=style%20eventMonitor\">Event monitor</a>\n" +
|
||||
" </div>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" </table>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" </table>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" <div id=\"hdr\">\n" +
|
||||
" <table border=\"0\" class=\"header\">\n" +
|
||||
" <tr>\n" +
|
||||
" <td style=\"padding:0\">\n" +
|
||||
" <form method=\"post\" action=\"/fhem\">\n" +
|
||||
" <input type=\"hidden\" name=\"fw_id\" value=\"7880\"/>\n" +
|
||||
" <input type=\"text\" name=\"cmd\" class=\"maininput\" size=\"40\" value=\"\"/>\n" +
|
||||
" </form>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>\n" +
|
||||
" </table>\n" +
|
||||
" </div>\n" +
|
||||
" <div id='content' >\n" +
|
||||
" <pre>{ \n" +
|
||||
" \"Arg\":\"room=habridge\", \n" +
|
||||
" \"Results\": [ \n" +
|
||||
" { \n" +
|
||||
" \"Name\":\"Arbeitslicht\", \n" +
|
||||
" \"PossibleSets\":\"on off\", \n" +
|
||||
" \"PossibleAttrs\":\"alias comment:textField-long eventMap group room suppressReading userReadings:textField-long verbose:0,1,2,3,4,5 readingList setList useSetExtensions disable disabledForIntervals event-on-change-reading event-on-update-reading event-aggregator event-min-interval stateFormat:textField-long timestamp-on-change-reading alexaName alexaRoom cmdIcon devStateIcon devStateStyle fhem_widget_command fhem_widget_command_2 fhem_widget_command_3 genericDeviceType:security,ignore,switch,outlet,light,blind,thermometer,thermostat,contact,garage,window,lock homebridgeMapping:textField-long icon sortby webCmd widgetOverride userattr\", \n" +
|
||||
" \"Internals\": { \n" +
|
||||
" \"NAME\": \"Arbeitslicht\", \n" +
|
||||
" \"NR\": \"28\", \n" +
|
||||
" \"STATE\": \"-\", \n" +
|
||||
" \"TYPE\": \"dummy\" \n" +
|
||||
" }, \n" +
|
||||
" \"Readings\": { \"state\": { \"Value\":\"on\", \"Time\":\"2017-12-14 15:41:05\" } }, \n" +
|
||||
" \"Attributes\": { \n" +
|
||||
" \"alexaName\": \"Arbeitslicht\", \n" +
|
||||
" \"alexaRoom\": \"alexaroom\", \n" +
|
||||
" \"fhem_widget_command\": \"{ \\u0022allowed_values\\u0022 : [ \\u0022on\\u0022 ], \\u0022order\\u0022 : 0}\", \n" +
|
||||
" \"icon\": \"scene_office\", \n" +
|
||||
" \"room\": \"Alexa,habridge\", \n" +
|
||||
" \"setList\": \"on off\", \n" +
|
||||
" \"stateFormat\": \"-\", \n" +
|
||||
" \"webCmd\": \"on\" \n" +
|
||||
" } \n" +
|
||||
" }, \n" +
|
||||
" { \n" +
|
||||
" \"Name\":\"DeckenlampeLinks\", \n" +
|
||||
" \"PossibleSets\":\"on off dim dimup dimdown HSV RGB sync pair unpair\", \n" +
|
||||
" \"PossibleAttrs\":\"alias comment:textField-long eventMap group room suppressReading userReadings:textField-long verbose:0,1,2,3,4,5 gamma dimStep defaultColor defaultRamp colorCast whitePoint event-on-change-reading event-on-update-reading event-aggregator event-min-interval stateFormat:textField-long timestamp-on-change-reading alexaName alexaRoom cmdIcon devStateIcon devStateStyle fhem_widget_command fhem_widget_command_2 fhem_widget_command_3 genericDeviceType:security,ignore,switch,outlet,light,blind,thermometer,thermostat,contact,garage,window,lock homebridgeMapping:textField-long icon sortby webCmd widgetOverride \n" +
|
||||
" <a href=\"/fhem?detail=AlleLampen\">AlleLampen</a> AlleLampen_map\n" +
|
||||
" <a href=\"/fhem?detail=DeckenLampen\">DeckenLampen</a> DeckenLampen_map structexclude userattr\", \n" +
|
||||
" \"Internals\": { \n" +
|
||||
" \"CONNECTION\": \"bridge-V3\", \n" +
|
||||
" \"DEF\": \"RGBW2 bridge-V3:10.2.3.3\", \n" +
|
||||
" \"IP\": \"10.2.3.3\", \n" +
|
||||
" \"LEDTYPE\": \"RGBW2\", \n" +
|
||||
" \"NAME\": \"DeckenlampeLinks\", \n" +
|
||||
" \"NR\": \"18\", \n" +
|
||||
" \"NTFY_ORDER\": \"50-DeckenlampeLinks\", \n" +
|
||||
" \"PORT\": \"8899\", \n" +
|
||||
" \"PROTO\": \"0\", \n" +
|
||||
" \"SLOT\": \"5\", \n" +
|
||||
" \"STATE\": \"off\", \n" +
|
||||
" \"TYPE\": \"WifiLight\" \n" +
|
||||
" }, \n" +
|
||||
" \"Readings\": { \n" +
|
||||
" \"RGB\": { \"Value\":\"000000\", \"Time\":\"2017-12-14 15:41:10\" }, \n" +
|
||||
" \"brightness\": { \"Value\":\"0\", \"Time\":\"2017-12-14 15:41:10\" }, \n" +
|
||||
" \"hue\": { \"Value\":\"0\", \"Time\":\"2017-12-14 15:41:10\" }, \n" +
|
||||
" \"saturation\": { \"Value\":\"0\", \"Time\":\"2017-12-14 15:41:10\" }, \n" +
|
||||
" \"state\": { \"Value\":\"off\", \"Time\":\"2017-12-14 15:41:10\" } \n" +
|
||||
" }, \n" +
|
||||
" \"Attributes\": { \n" +
|
||||
" \"AlleLampen\": \"AlleLampen\", \n" +
|
||||
" \"DeckenLampen\": \"DeckenLampen\", \n" +
|
||||
" \"fhem_widget_command\": \"{ \\u0022locations\\u0022 : [ \\u0022APP\\u0022, \\u0022WATCH\\u0022, \\u0022WIDGET\\u0022 ], \\u0022allowed_values\\u0022 : [ \\u0022off\\u0022, \\u0022on\\u0022 ], \\u0022order\\u0022 : 6}\", \n" +
|
||||
" \"room\": \"habridge,Alexa,WG-Zimmer\", \n" +
|
||||
" \"userattr\": \"AlleLampen AlleLampen_map\n" +
|
||||
" <a href=\"/fhem?detail=DeckenLampen\">DeckenLampen</a> DeckenLampen_map structexclude\", \n" +
|
||||
" \"webCmd\": \"RGB\", \n" +
|
||||
" \"widgetOverride\": \"RGB:colorpicker,RGB\" \n" +
|
||||
" } \n" +
|
||||
" } ], \n" +
|
||||
" \"totalResultsReturned\":2 \n" +
|
||||
"}\n" +
|
||||
" </pre>\n" +
|
||||
" </div>\n" +
|
||||
" </body>\n" +
|
||||
"</html>";
|
||||
|
||||
public final static String TestData2 = " <div id='content' >\n" +
|
||||
" <pre>\n" + "{ \"Arg\":\"room=HaBridge\", \"Results\": [ { \"Name\":\"wifi_steckdose3\", \"PossibleSets\":\"on:noArg off:noArg off on toggle\", \"PossibleAttrs\":\"alias comment:textField-long eventMap group room suppressReading userReadings:textField-long verbose:0,1,2,3,4,5 IODev qos retain publishSet publishSet_.* subscribeReading_.* autoSubscribeReadings event-on-change-reading event-on-update-reading event-aggregator event-min-interval stateFormat:textField-long timestamp-on-change-reading alarmDevice:Actor,Sensor alarmSettings cmdIcon devStateIcon devStateStyle icon lightSceneParamsToSave lightSceneRestoreOnlyIfChanged:1,0 sortby structexclude webCmd webCmdLabel:textField-long widgetOverride userattr\", \"Internals\": { \"CHANGED\": \"null\", \"NAME\": \"wifi_steckdose3\", \"NR\": \"270\", \"STATE\": \"off\", \"TYPE\": \"MQTT_DEVICE\", \"retain\": \"*:1 \" }, \"Readings\": { \"state\": { \"Value\":\"OFF\", \"Time\":\"2018-01-01 23:01:21\" }, \"transmission-state\": { \"Value\":\"subscription acknowledged\", \"Time\":\"2018-01-03 22:34:00\" } }, \"Attributes\": { \"IODev\": \"myBroker\", \"alias\": \"Stecki\", \"devStateIcon\": \"on:black_Steckdose.on off:black_Steckdose.off\", \"event-on-change-reading\": \"state\", \"eventMap\": \"ON:on OFF:off\", \"publishSet\": \"on off toggle /SmartHome/az/stecker/cmnd/POWER\", \"retain\": \"1\", \"room\": \"HaBridge,Arbeitszimmer,mqtt\", \"stateFormat\": \"state\", \"subscribeReading_state\": \"/SmartHome/az/stecker/stat/POWER\", \"webCmd\": \"on:off:toggle\" } } ], \"totalResultsReturned\":1 }" +
|
||||
" </pre>\n" +
|
||||
" </div>\n" +
|
||||
" </body>\n" +
|
||||
"</html>";
|
||||
public final static String TestData3 ="DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" +
|
||||
"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" +
|
||||
"<head root=\"/fhem\">\n" +
|
||||
"<title>Home, Sweet Home</title>\n" +
|
||||
"<link rel=\"shortcut icon\" href=\"/fhem/icons/favicon\" />\n" +
|
||||
"<meta charset=\"UTF-8\">\n" +
|
||||
"<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n" +
|
||||
"<link href=\"/fhem/pgm2/style.css?v=1515015198\" rel=\"stylesheet\"/>\n" +
|
||||
"<link href=\"/fhem/pgm2/jquery-ui.min.css\" rel=\"stylesheet\"/>\n" +
|
||||
"<script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/jquery.min.js\"></script>\n" +
|
||||
"<script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/jquery-ui.min.js\"></script>\n" +
|
||||
"<script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb.js\"></script>\n" +
|
||||
"<script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/doif.js\"></script>\n" +
|
||||
"<script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fronthemEditor.js\"></script>\n" +
|
||||
"<script attr='' type=\"text/javascript\" src=\"/fhem/pgm2/fhemweb_readingsGroup.js\"></script>\n" +
|
||||
"</head>\n" +
|
||||
"<body name='Home, Sweet Home' fw_id='1490' generated=\"1515770038\" longpoll=\"websocket\" data-confirmDelete='1' data-confirmJSError='1' data-addHtmlTitle='1' data-availableJs='sortable,iconLabel,readingsHistory,colorpicker,iconButtons,fbcalllist,knob,weekprofile,iconRadio,readingsGroup,iconSwitch,uzsu' data-webName='WEB '>\n" +
|
||||
"<div id=\"menuScrollArea\">\n" +
|
||||
"</div>\n" +
|
||||
"<div id='content' >\n" +
|
||||
"<pre>{\n" +
|
||||
"\"Arg\":\"room=HaBridge\",\n" +
|
||||
"\"Results\": [\n" +
|
||||
"{\n" +
|
||||
"\"Name\":\"<a href='/fhem?detail=wifi_steckdose3'>wifi_steckdose3</a>\",\n" +
|
||||
"\"PossibleSets\":\"on:noArg off:noArg off on toggle\",\n" +
|
||||
"\"PossibleAttrs\":\"alias comment:textField-long eventMap group room suppressReading userReadings:textField-long verbose:0,1,2,3,4,5 IODev qos retain publishSet publishSet_.* subscribeReading_.* autoSubscribeReadings event-on-change-reading event-on-update-reading event-aggregator event-min-interval stateFormat:textField-long timestamp-on-change-reading alarmDevice:Actor,Sensor alarmSettings cmdIcon devStateIcon devStateStyle icon lightSceneParamsToSave lightSceneRestoreOnlyIfChanged:1,0 sortby structexclude webCmd webCmdLabel:textField-long widgetOverride userattr\",\n" +
|
||||
"\"Internals\": {\n" +
|
||||
"\"NAME\": \"<a href='/fhem?detail=wifi_steckdose3'>wifi_steckdose3</a>\",\n" +
|
||||
"\"NR\": \"270\",\n" +
|
||||
"\"STATE\": \"off\",\n" +
|
||||
"\"TYPE\": \"MQTT_DEVICE\",\n" +
|
||||
"\"retain\": \"*:1 \"\n" +
|
||||
"},\n" +
|
||||
"\"Readings\": {\n" +
|
||||
"\"state\": { \"Value\":\"OFF\", \"Time\":\"2018-01-07 05:16:01\" },\n" +
|
||||
"\"transmission-state\": { \"Value\":\"incoming publish received\", \"Time\":\"2018-01-07 05:16:01\" }\n" +
|
||||
"},\n" +
|
||||
"\"Attributes\": {\n" +
|
||||
"\"IODev\": \"<a href='/fhem?detail=myBroker'>myBroker</a>\",\n" +
|
||||
"\"alias\": \"Stecki\",\n" +
|
||||
"\"devStateIcon\": \"on:black_Steckdose.on off:black_Steckdose.off\",\n" +
|
||||
"\"event-on-change-reading\": \"state\",\n" +
|
||||
"\"eventMap\": \"ON:on OFF:off\",\n" +
|
||||
"\"publishSet\": \"on off toggle /SmartHome/az/stecker/cmnd/POWER\",\n" +
|
||||
"\"retain\": \"1\",\n" +
|
||||
"\"room\": \"HaBridge,Arbeitszimmer,mqtt\",\n" +
|
||||
"\"stateFormat\": \"state\",\n" +
|
||||
"\"subscribeReading_state\": \"/SmartHome/az/stecker/stat/POWER\",\n" +
|
||||
"\"webCmd\": \"on:off:toggle\"\n" +
|
||||
"}\n" +
|
||||
"} ],\n" +
|
||||
"\"totalResultsReturned\":1\n" +
|
||||
"}\n" +
|
||||
"</pre>\n" +
|
||||
"</div>\n" +
|
||||
"</body></html>";
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
package com.bwssystems.HABridge.plugins.fhem;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class Result {
|
||||
|
||||
@SerializedName("Name")
|
||||
@Expose
|
||||
private String name;
|
||||
@SerializedName("PossibleSets")
|
||||
@Expose
|
||||
private String possibleSets;
|
||||
@SerializedName("PossibleAttrs")
|
||||
@Expose
|
||||
private String possibleAttrs;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getPossibleSets() {
|
||||
return possibleSets;
|
||||
}
|
||||
|
||||
public void setPossibleSets(String possibleSets) {
|
||||
this.possibleSets = possibleSets;
|
||||
}
|
||||
|
||||
public String getPossibleAttrs() {
|
||||
return possibleAttrs;
|
||||
}
|
||||
|
||||
public void setPossibleAttrs(String possibleAttrs) {
|
||||
this.possibleAttrs = possibleAttrs;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro;
|
||||
|
||||
public class FibaroFilter {
|
||||
boolean useSaveLogs;
|
||||
boolean useUserDescription;
|
||||
boolean scenesLiliCmddOnly;
|
||||
boolean replaceTrash;
|
||||
|
||||
public boolean isUseSaveLogs() {
|
||||
return useSaveLogs;
|
||||
}
|
||||
public void setUseSaveLogs(boolean useSaveLogs) {
|
||||
this.useSaveLogs = useSaveLogs;
|
||||
}
|
||||
public boolean isUseUserDescription() {
|
||||
return useUserDescription;
|
||||
}
|
||||
public void setUseUserDescription(boolean useUserDescription) {
|
||||
this.useUserDescription = useUserDescription;
|
||||
}
|
||||
public boolean isReplaceTrash() {
|
||||
return replaceTrash;
|
||||
}
|
||||
public void setReplaceTrash(boolean replaceTrash) {
|
||||
this.replaceTrash = replaceTrash;
|
||||
}
|
||||
public boolean isScenesLiliCmddOnly() {
|
||||
return scenesLiliCmddOnly;
|
||||
}
|
||||
public void setScenesLiliCmddOnly(boolean scenesLiliCmddOnly) {
|
||||
this.scenesLiliCmddOnly = scenesLiliCmddOnly;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.BridgeSettings;
|
||||
import com.bwssystems.HABridge.DeviceMapTypes;
|
||||
import com.bwssystems.HABridge.Home;
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.plugins.fibaro.json.Device;
|
||||
import com.bwssystems.HABridge.plugins.fibaro.json.Scene;
|
||||
|
||||
public class FibaroHome implements Home
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(FibaroHome.class);
|
||||
private Map<String, FibaroInfo> fibaros;
|
||||
private Boolean validFibaro;
|
||||
private boolean closed;
|
||||
|
||||
public FibaroHome(BridgeSettings bridgeSettings)
|
||||
{
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
public List<Device> getDevices()
|
||||
{
|
||||
log.debug("consolidating devices for fibaros");
|
||||
Iterator<String> keys = fibaros.keySet().iterator();
|
||||
ArrayList<Device> deviceList = new ArrayList<>();
|
||||
while(keys.hasNext())
|
||||
{
|
||||
String key = keys.next();
|
||||
for(Device device : fibaros.get(key).getDevices())
|
||||
deviceList.add(device);
|
||||
}
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
public List<Scene> getScenes()
|
||||
{
|
||||
log.debug("consolidating scenes for fibaros");
|
||||
Iterator<String> keys = fibaros.keySet().iterator();
|
||||
ArrayList<Scene> sceneList = new ArrayList<>();
|
||||
while(keys.hasNext())
|
||||
{
|
||||
String key = keys.next();
|
||||
for(Scene scene : fibaros.get(key).getScenes())
|
||||
sceneList.add(scene);
|
||||
}
|
||||
return sceneList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body)
|
||||
{
|
||||
// Not a device handler
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItems(String type)
|
||||
{
|
||||
if(validFibaro)
|
||||
{
|
||||
if(type.equalsIgnoreCase(DeviceMapTypes.FIBARO_DEVICE[DeviceMapTypes.typeIndex]))
|
||||
return getDevices();
|
||||
if(type.equalsIgnoreCase(DeviceMapTypes.FIBARO_SCENE[DeviceMapTypes.typeIndex]))
|
||||
return getScenes();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public Home createHome(BridgeSettings bridgeSettings)
|
||||
{
|
||||
validFibaro = bridgeSettings.getBridgeSettingsDescriptor().isValidFibaro();
|
||||
log.info("Fibaro Home created." + (validFibaro ? "" : " No Fibaros configured."));
|
||||
if(validFibaro)
|
||||
{
|
||||
fibaros = new HashMap<String, FibaroInfo>();
|
||||
Iterator<NamedIP> theList = bridgeSettings.getBridgeSettingsDescriptor().getFibaroAddress().getDevices().iterator();
|
||||
while(theList.hasNext())
|
||||
{
|
||||
NamedIP aFibaro = theList.next();
|
||||
fibaros.put(aFibaro.getName(), new FibaroInfo(aFibaro));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeHome()
|
||||
{
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
fibaros = null;
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.plugins.fibaro.json.Device;
|
||||
import com.bwssystems.HABridge.plugins.fibaro.json.Room;
|
||||
import com.bwssystems.HABridge.plugins.fibaro.json.Scene;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class FibaroInfo
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(FibaroInfo.class);
|
||||
|
||||
private final NamedIP fibaroAddress;
|
||||
private final String fibaroAuth;
|
||||
private final Gson gson;
|
||||
private Boolean isDevMode;
|
||||
private FibaroFilter theFilters;
|
||||
|
||||
public FibaroInfo(NamedIP addressName)
|
||||
{
|
||||
super();
|
||||
fibaroAddress = addressName;
|
||||
fibaroAuth = "Basic " + new String(Base64.encodeBase64((addressName.getUsername() + ":" + addressName.getPassword()).getBytes()));
|
||||
isDevMode = Boolean.parseBoolean(System.getProperty("dev.mode", "false"));
|
||||
gson = new Gson();
|
||||
theFilters = null;
|
||||
if(fibaroAddress.getExtensions() != null) {
|
||||
try {
|
||||
theFilters = gson.fromJson(fibaroAddress.getExtensions(), FibaroFilter.class);
|
||||
} catch(Exception e) {
|
||||
log.warn("Could not read fibaro filters - continuing with defaults.");
|
||||
theFilters = null;
|
||||
}
|
||||
}
|
||||
|
||||
if(theFilters == null) {
|
||||
theFilters = new FibaroFilter();
|
||||
theFilters.setUseSaveLogs(false);
|
||||
theFilters.setUseUserDescription(false);
|
||||
theFilters.setScenesLiliCmddOnly(false);
|
||||
theFilters.setReplaceTrash(true);
|
||||
}
|
||||
}
|
||||
|
||||
private String request(String request)
|
||||
{
|
||||
String result = null;
|
||||
try
|
||||
{
|
||||
URL url = new URL("http://" + fibaroAddress.getIp() + ":" + fibaroAddress.getPort() + request);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setRequestProperty("Authorization", fibaroAuth);
|
||||
connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
|
||||
connection.connect();
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
String line;
|
||||
while((line = br.readLine()) != null)
|
||||
{
|
||||
buffer.append(line).append("\n");
|
||||
}
|
||||
br.close();
|
||||
result = buffer.toString();
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
log.warn("Error while get getJson: {} ", request, e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String replaceTrash(String name)
|
||||
{
|
||||
String sanitizedName = name.replaceAll("[0-9:/-]", "");
|
||||
sanitizedName = name.replaceAll("\\s+", " ");
|
||||
return sanitizedName.trim();
|
||||
}
|
||||
|
||||
private Room[] getRooms()
|
||||
{
|
||||
String result = null;
|
||||
if(isDevMode)
|
||||
result = FibaroTestData.RoomTestData;
|
||||
else
|
||||
result = request("/api/rooms");
|
||||
log.debug("getRooms response: <<<" + result + ">>>");
|
||||
Room[] rooms = result == null ? new Room[0] : gson.fromJson(result, Room[].class);
|
||||
if(theFilters.isReplaceTrash())
|
||||
for(Room r : rooms)
|
||||
r.setName(replaceTrash(r.getName()));
|
||||
return rooms;
|
||||
}
|
||||
|
||||
public Device[] getDevices()
|
||||
{
|
||||
Room[] rooms = getRooms();
|
||||
|
||||
log.debug("getDevices Found: " + rooms.length + " rooms");
|
||||
|
||||
String result = null;
|
||||
if(isDevMode)
|
||||
result = FibaroTestData.DeviceTestData;
|
||||
else
|
||||
result = request("/api/devices?enabled=true&visible=true");
|
||||
log.debug("getDevices response: <<<" + result + ">>>");
|
||||
Device[] all_devices = result == null ? new Device[0] : gson.fromJson(result, Device[].class);
|
||||
|
||||
int count = 0;
|
||||
for(Device d : all_devices)
|
||||
if(d.getRoomID() > 0 && (theFilters.isUseSaveLogs() ? "true".equals(d.getProperties().getSaveLogs()) : true))
|
||||
count++;
|
||||
|
||||
Device[] devices = new Device[count];
|
||||
int i = 0;
|
||||
for(Device d : all_devices)
|
||||
if(d.getRoomID() > 0 && (theFilters.isUseSaveLogs() ? "true".equals(d.getProperties().getSaveLogs()) : true))
|
||||
{
|
||||
if(theFilters.isUseUserDescription() && d.getProperties().getUserDescription() != null && !d.getProperties().getUserDescription().isEmpty())
|
||||
d.setName(d.getProperties().getUserDescription());
|
||||
if(theFilters.isReplaceTrash())
|
||||
d.setName(replaceTrash(d.getName()));
|
||||
|
||||
devices[i++] = d;
|
||||
|
||||
for(Room room : rooms)
|
||||
if(d.getRoomID() == room.getId())
|
||||
d.setRoomName(room.getName());
|
||||
|
||||
d.fibaroaddress = fibaroAddress.getIp();
|
||||
d.fibaroport = fibaroAddress.getPort();
|
||||
d.fibaroAuth = fibaroAuth;
|
||||
d.fibaroname = fibaroAddress.getName();
|
||||
}
|
||||
|
||||
log.debug("getDevices Found: " + devices.length + " devices");
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
public Scene[] getScenes()
|
||||
{
|
||||
Room[] rooms = getRooms();
|
||||
|
||||
String result = null;
|
||||
if(isDevMode)
|
||||
result = FibaroTestData.SceneTestData;
|
||||
else
|
||||
result = request("/api/scenes?enabled=true&visible=true");
|
||||
log.debug("getScenes response: <<<" + result + ">>>");
|
||||
Scene[] all_scenes = result == null ? new Scene[0] : gson.fromJson(result, Scene[].class);
|
||||
|
||||
int count = 0;
|
||||
for(Scene s : all_scenes)
|
||||
if(!theFilters.isScenesLiliCmddOnly() || s.getLiliStartCommand() != null && !s.getLiliStartCommand().isEmpty())
|
||||
count++;
|
||||
Scene[] scenes = new Scene[count];
|
||||
int i = 0;
|
||||
for(Scene s : all_scenes)
|
||||
if(!theFilters.isScenesLiliCmddOnly() || s.getLiliStartCommand() != null && !s.getLiliStartCommand().isEmpty())
|
||||
{
|
||||
if(theFilters.isReplaceTrash())
|
||||
s.setName(replaceTrash(s.getName()));
|
||||
|
||||
scenes[i++] = s;
|
||||
|
||||
for(Room room : rooms)
|
||||
if(s.getRoomID() == room.getId())
|
||||
s.setRoomName(room.getName());
|
||||
|
||||
s.fibaroaddress = fibaroAddress.getIp();
|
||||
s.fibaroport = fibaroAddress.getPort();
|
||||
s.fibaroAuth = fibaroAuth;
|
||||
s.fibaroname = fibaroAddress.getName();
|
||||
}
|
||||
log.debug("getScenes Found: " + count + " scenes");
|
||||
return scenes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro;
|
||||
|
||||
public class FibaroTestData {
|
||||
public final static String DeviceTestData = "[{\"id\":7,\"name\":\"Deckenspots\",\"roomID\":12,\"type\":\"com.fibaro.FGD212\",\"baseType\":\"com.fibaro.multilevelSwitch\",\"enabled\":true,\"visible\":true,\"isPlugin\":false,\"parentId\":5,\"remoteGatewayId\":0,\"viewXml\":false,\"configXml\":false,\"interfaces\":[\"deviceGrouping\",\"energy\",\"levelChange\",\"light\",\"power\",\"zwave\",\"zwaveAlarm\",\"zwaveMultiChannelAssociation\",\"zwaveProtection\",\"zwaveSceneActivation\"],\"properties\":{\"pollingTimeSec\":0,\"zwaveCompany\":\"Fibargroup\",\"zwaveInfo\":\"3,4,5\",\"zwaveVersion\":\"3.5\",\"RFProtectionState\":\"0\",\"RFProtectionSupport\":\"3\",\"alarmLevel\":\"0\",\"alarmType\":\"0\",\"configured\":true,\"dead\":\"false\",\"deviceControlType\":\"23\",\"deviceGroup\":\"[]\",\"deviceGroupMaster\":\"0\",\"deviceIcon\":\"15\",\"emailNotificationID\":\"0\",\"emailNotificationType\":\"0\",\"endPointId\":\"1\",\"energy\":\"7.23\",\"isLight\":\"true\",\"liliOffCommand\":\"\",\"liliOnCommand\":\"\",\"localProtectionState\":\"0\",\"localProtectionSupport\":\"5\",\"log\":\"\",\"logTemp\":\"\",\"manufacturer\":\"\",\"markAsDead\":\"true\",\"model\":\"\",\"nodeId\":\"2\",\"parametersTemplate\":\"796\",\"power\":\"5.80\",\"productInfo\":\"1,15,1,2,16,0,3,5\",\"protectionExclusiveControl\":\"0\",\"protectionExclusiveControlSupport\":\"false\",\"protectionState\":\"0\",\"protectionTimeout\":\"0\",\"protectionTimeoutSupport\":\"false\",\"pushNotificationID\":\"0\",\"pushNotificationType\":\"0\",\"remoteGatewayId\":\"0\",\"saveLogs\":\"true\",\"sceneActivation\":\"25\",\"serialNumber\":\"h'000000000001c1b4\",\"showEnergy\":\"true\",\"smsNotificationID\":\"0\",\"smsNotificationType\":\"0\",\"useTemplate\":\"true\",\"userDescription\":\"\",\"value\":\"5\"},\"actions\":{\"reconfigure\":0,\"reset\":0,\"sceneActivationSet\":0,\"setValue\":1,\"startLevelDecrease\":0,\"startLevelIncrease\":0,\"stopLevelChange\":0,\"turnOff\":0,\"turnOn\":0},\"created\":1516643104,\"modified\":1516643104,\"sortOrder\":1},{\"id\":13,\"name\":\"Licht Küche\",\"roomID\":13,\"type\":\"com.fibaro.binarySwitch\",\"baseType\":\"com.fibaro.actor\",\"enabled\":true,\"visible\":true,\"isPlugin\":false,\"parentId\":10,\"remoteGatewayId\":0,\"viewXml\":false,\"configXml\":fals" +
|
||||
"e,\"interfaces\":[\"deviceGrouping\",\"energy\",\"light\",\"power\",\"zwave\",\"zwaveMultiChannelAssociation\",\"zwaveProtection\"],\"properties\":{\"pollingTimeSec\":0,\"zwaveCompany\":\"Fibargroup\",\"zwaveInfo\":\"3,4,5\",\"zwaveVersion\":\"3.2\",\"RFProtectionState\":\"0\",\"RFProtectionSupport\":\"3\",\"configured\":true,\"dead\":\"false\",\"deviceControlType\":\"2\",\"deviceGroup\":\"[]\",\"deviceGroupMaster\":\"0\",\"deviceIcon\":\"2\",\"emailNotificationID\":\"0\",\"emailNotificationType\":\"0\",\"endPointId\":\"1\",\"energy\":\"9.51\",\"isLight\":\"true\",\"liliOffCommand\":\"\",\"liliOnCommand\":\"\",\"localProtectionState\":\"0\",\"localProtectionSupport\":\"5\",\"log\":\"\",\"logTemp\":\"\",\"manufacturer\":\"\",\"markAsDead\":\"true\",\"model\":\"\",\"nodeId\":\"3\",\"parametersTemplate\":\"781\",\"power\":\"16.00\",\"productInfo\":\"1,15,2,3,16,0,3,2\",\"protectionExclusiveControl\":\"0\",\"protectionExclusiveControlSupport\":\"false\",\"protectionState\":\"0\",\"protectionTimeout\":\"0\",\"protectionTimeoutSupport\":\"false\",\"pushNotificationID\":\"0\",\"pushNotificationType\":\"0\",\"remoteGatewayId\":\"0\",\"saveLogs\":\"true\",\"serialNumber\":\"h'000000000000450d\",\"showEnergy\":\"true\",\"smsNotificationID\":\"0\",\"smsNotificationType\":\"0\",\"useTemplate\":\"true\",\"userDescription\":\"\",\"value\":\"true\"},\"actions\":{\"reconfigure\":0,\"reset\":0,\"turnOff\":0,\"turnOn\":0},\"created\":1516643104,\"modified\":1516643104,\"sortOrder\":2},{\"id\":14,\"name\":\"Lampe Tisch\",\"roomID\":14,\"type\":\"com.fibaro.binarySwitch\",\"baseType\":\"com.fibaro.actor\",\"enabled\":true,\"visible\":true,\"isPlugin\":false,\"parentId\":10,\"remoteGatewayId\":0,\"viewXml\":false,\"configXml\":false,\"interfaces\":[\"deviceGrouping\",\"energy\",\"light\",\"power\",\"zwave\",\"zwaveMultiChannelAssociation\",\"zwaveProtection\"],\"properties\":{\"pollingTimeSec\":0,\"zwaveCompany\":\"Fibargroup\",\"zwaveInfo\":\"3,4,5\",\"zwaveVersion\":\"3.2\",\"RFProtectionState\":\"0\",\"RFProtectionSupport\":\"3\",\"configured\":true,\"dead\":\"false\",\"deviceControlType\":\"2\",\"deviceGroup\":\"[]\",\"deviceGroupMaster\":\"0\",\"deviceIcon\":\"2\",\"emailNotificationID\":\"0\",\"emailNotificationType\":\"0\",\"endPointId\":\"2\",\"energy\":\"29.15\",\"isLight\":\"true\",\"liliOffCommand\":\"\",\"liliOnCommand\":\"\",\"localProtectionState\":" +
|
||||
"\"0\",\"localProtectionSupport\":\"5\",\"log\":\"\",\"logTemp\":\"\",\"manufacturer\":\"\",\"markAsDead\":\"true\",\"model\":\"\",\"nodeId\":\"3\",\"parametersTemplate\":\"781\",\"power\":\"11.50\",\"productInfo\":\"1,15,2,3,16,0,3,2\",\"protectionExclusiveControl\":\"0\",\"protectionExclusiveControlSupport\":\"false\",\"protectionState\":\"0\",\"protectionTimeout\":\"0\",\"protectionTimeoutSupport\":\"false\",\"pushNotificationID\":\"0\",\"pushNotificationType\":\"0\",\"remoteGatewayId\":\"0\",\"saveLogs\":\"true\",\"serialNumber\":\"h'000000000000450d\",\"showEnergy\":\"true\",\"smsNotificationID\":\"0\",\"smsNotificationType\":\"0\",\"useTemplate\":\"true\",\"userDescription\":\"\",\"value\":\"true\"},\"actions\":{\"reconfigure\":0,\"reset\":0,\"turnOff\":0,\"turnOn\":0},\"created\":1516643104,\"modified\":1516643104,\"sortOrder\":3},{\"id\":18,\"name\":\"Licht\",\"roomID\":16,\"type\":\"com.fibaro.binarySwitch\",\"baseType\":\"com.fibaro.actor\",\"enabled\":true,\"visible\":true,\"isPlugin\":false,\"parentId\":15,\"remoteGatewayId\":0,\"viewXml\":false,\"configXml\":false,\"interfaces\":[\"deviceGrouping\",\"energy\",\"light\",\"power\",\"zwave\",\"zwaveMultiChannelAssociation\",\"zwaveProtection\"],\"properties\":{\"pollingTimeSec\":0,\"zwaveCompany\":\"Fibargroup\",\"zwaveInfo\":\"3,4,5\",\"zwaveVersion\":\"3.2\",\"RFProtectionState\":\"0\",\"RFProtectionSupport\":\"3\",\"configured\":true,\"dead\":\"false\",\"deviceControlType\":\"2\",\"deviceGroup\":\"[]\",\"deviceGroupMaster\":\"0\",\"deviceIcon\":\"2\",\"emailNotificationID\":\"0\",\"emailNotificationType\":\"0\",\"endPointId\":\"1\",\"energy\":\"2.70\",\"isLight\":\"true\",\"liliOffCommand\":\"\",\"liliOnCommand\":\"\",\"localProtectionState\":\"0\",\"localProtectionSupport\":\"5\",\"log\":\"\",\"logTemp\":\"\",\"manufacturer\":\"\",\"markAsDead\":\"true\",\"model\":\"\",\"nodeId\":\"4\",\"parametersTemplate\":\"781\",\"power\":\"0.00\",\"productInfo\":\"1,15,2,3,16,0,3,2\",\"protectionExclusiveControl\":\"0\",\"protectionExclusiveControlSupport\":\"false\",\"protectionState\":\"0\",\"protectionTimeout\":\"0\",\"protectionTimeoutSupport\":\"false\",\"pushNotificationID\":\"0\",\"pushNotificationType\":\"0\",\"remoteGatewayId\":\"0\",\"saveLogs\":\"true\",\"serialNumber\":\"h'00000000000044b4\",\"showEnergy\":\"true\",\"smsNotificationID\":\"0\",\"smsNotificationType\":\"0\",\"useTempl" +
|
||||
"ate\":\"true\",\"userDescription\":\"\",\"value\":\"false\"},\"actions\":{\"reconfigure\":0,\"reset\":0,\"turnOff\":0,\"turnOn\":0},\"created\":1516643104,\"modified\":1516643104,\"sortOrder\":4},{\"id\":26,\"name\":\"Licht\",\"roomID\":5,\"type\":\"com.fibaro.FGD212\",\"baseType\":\"com.fibaro.multilevelSwitch\",\"enabled\":true,\"visible\":true,\"isPlugin\":false,\"parentId\":24,\"remoteGatewayId\":0,\"viewXml\":false,\"configXml\":false,\"interfaces\":[\"deviceGrouping\",\"energy\",\"levelChange\",\"light\",\"power\",\"zwave\",\"zwaveAlarm\",\"zwaveMultiChannelAssociation\",\"zwaveProtection\",\"zwaveSceneActivation\"],\"properties\":{\"pollingTimeSec\":0,\"zwaveCompany\":\"Fibargroup\",\"zwaveInfo\":\"3,4,5\",\"zwaveVersion\":\"3.5\",\"RFProtectionState\":\"0\",\"RFProtectionSupport\":\"3\",\"alarmLevel\":\"0\",\"alarmType\":\"0\",\"configured\":true,\"dead\":\"false\",\"deviceControlType\":\"23\",\"deviceGroup\":\"[]\",\"deviceGroupMaster\":\"0\",\"deviceIcon\":\"15\",\"emailNotificationID\":\"0\",\"emailNotificationType\":\"0\",\"endPointId\":\"1\",\"energy\":\"28.02\",\"isLight\":\"true\",\"liliOffCommand\":\"\",\"liliOnCommand\":\"\",\"localProtectionState\":\"0\",\"localProtectionSupport\":\"5\",\"log\":\"\",\"logTemp\":\"\",\"manufacturer\":\"\",\"markAsDead\":\"true\",\"model\":\"\",\"nodeId\":\"7\",\"parametersTemplate\":\"796\",\"power\":\"0.00\",\"productInfo\":\"1,15,1,2,16,0,3,5\",\"protectionExclusiveControl\":\"0\",\"protectionExclusiveControlSupport\":\"false\",\"protectionState\":\"0\",\"protectionTimeout\":\"0\",\"protectionTimeoutSupport\":\"false\",\"pushNotificationID\":\"0\",\"pushNotificationType\":\"0\",\"remoteGatewayId\":\"0\",\"saveLogs\":\"true\",\"sceneActivation\":\"0\",\"serialNumber\":\"h'0000000000001fec\",\"showEnergy\":\"true\",\"smsNotificationID\":\"0\",\"smsNotificationType\":\"0\",\"useTemplate\":\"true\",\"userDescription\":\"\",\"value\":\"0\"},\"actions\":{\"reconfigure\":0,\"reset\":0,\"sceneActivationSet\":0,\"setValue\":1,\"startLevelDecrease\":0,\"startLevelIncrease\":0,\"stopLevelChange\":0,\"turnOff\":0,\"turnOn\":0},\"created\":1516643105,\"modified\":1516643105,\"sortOrder\":5},{\"id\":57,\"name\":\"Fenster rechts\",\"roomID\":14,\"type\":\"com.fibaro.FGRM222\",\"baseType\":\"com.fibaro.FGR\",\"enabled\":true,\"visible\":true,\"isPlugin\":false,\"parentId\":56,\"remoteGatewayId\"" +
|
||||
":0,\"viewXml\":false,\"configXml\":false,\"interfaces\":[\"energy\",\"levelChange\",\"power\",\"zwave\",\"zwaveMultiChannelAssociation\",\"zwaveProtection\",\"zwaveSceneActivation\"],\"properties\":{\"pollingTimeSec\":0,\"zwaveCompany\":\"Fibargroup\",\"zwaveInfo\":\"3,3,52\",\"zwaveVersion\":\"25.25\",\"RFProtectionState\":\"0\",\"RFProtectionSupport\":\"3\",\"configured\":true,\"dead\":\"false\",\"deviceControlType\":\"54\",\"deviceIcon\":\"87\",\"emailNotificationID\":\"0\",\"emailNotificationType\":\"0\",\"endPointId\":\"0\",\"energy\":\"0.78\",\"liliOffCommand\":\"\",\"liliOnCommand\":\"\",\"localProtectionState\":\"0\",\"localProtectionSupport\":\"5\",\"log\":\"\",\"logTemp\":\"\",\"manufacturer\":\"\",\"markAsDead\":\"true\",\"model\":\"\",\"nodeId\":\"19\",\"parametersTemplate\":\"721\",\"power\":\"0.00\",\"productInfo\":\"1,15,3,2,16,0,25,25\",\"protectionExclusiveControl\":\"0\",\"protectionExclusiveControlSupport\":\"false\",\"protectionLocal\":\"0\",\"protectionLocalSupport\":\"5\",\"protectionRF\":\"0\",\"protectionRFSupport\":\"3\",\"protectionState\":\"0\",\"protectionTimeout\":\"0\",\"protectionTimeoutSupport\":\"false\",\"pushNotificationID\":\"0\",\"pushNotificationType\":\"0\",\"remoteGatewayId\":\"0\",\"saveLogs\":\"true\",\"sceneActivation\":\"0\",\"serialNumber\":\"\",\"showEnergy\":\"true\",\"smsNotificationID\":\"0\",\"smsNotificationType\":\"0\",\"useTemplate\":\"true\",\"userDescription\":\"\",\"value\":\"0\",\"value2\":\"0\"},\"actions\":{\"close\":0,\"open\":0,\"reconfigure\":0,\"reset\":0,\"sceneActivationSet\":0,\"setValue\":1,\"setValue2\":1,\"startLevelDecrease\":0,\"startLevelIncrease\":0,\"stop\":0,\"stopLevelChange\":0},\"created\":1516643105,\"modified\":1516643105,\"sortOrder\":12},{\"id\":60,\"name\":\"Fenster mitte\",\"roomID\":14,\"type\":\"com.fibaro.FGRM222\",\"baseType\":\"com.fibaro.FGR\",\"enabled\":true,\"visible\":true,\"isPlugin\":false,\"parentId\":59,\"remoteGatewayId\":0,\"viewXml\":false,\"configXml\":false,\"interfaces\":[\"energy\",\"levelChange\",\"power\",\"zwave\",\"zwaveMultiChannelAssociation\",\"zwaveProtection\",\"zwaveSceneActivation\"],\"properties\":{\"pollingTimeSec\":0,\"zwaveCompany\":\"Fibargroup\",\"zwaveInfo\":\"3,3,52\",\"zwaveVersion\":\"25.25\",\"RFProtectionState\":\"0\",\"RFProtectionSupport\":\"3\",\"configured\":true,\"dead\":\"false\",\"deviceControlT" +
|
||||
"ype\":\"54\",\"deviceIcon\":\"87\",\"emailNotificationID\":\"0\",\"emailNotificationType\":\"0\",\"endPointId\":\"0\",\"energy\":\"0.71\",\"liliOffCommand\":\"\",\"liliOnCommand\":\"\",\"localProtectionState\":\"0\",\"localProtectionSupport\":\"5\",\"log\":\"\",\"logTemp\":\"\",\"manufacturer\":\"\",\"markAsDead\":\"true\",\"model\":\"\",\"nodeId\":\"20\",\"parametersTemplate\":\"721\",\"power\":\"0.00\",\"productInfo\":\"1,15,3,2,16,0,25,25\",\"protectionExclusiveControl\":\"0\",\"protectionExclusiveControlSupport\":\"false\",\"protectionLocal\":\"0\",\"protectionLocalSupport\":\"5\",\"protectionRF\":\"0\",\"protectionRFSupport\":\"3\",\"protectionState\":\"0\",\"protectionTimeout\":\"0\",\"protectionTimeoutSupport\":\"false\",\"pushNotificationID\":\"0\",\"pushNotificationType\":\"0\",\"remoteGatewayId\":\"0\",\"saveLogs\":\"true\",\"sceneActivation\":\"26\",\"serialNumber\":\"\",\"showEnergy\":\"true\",\"smsNotificationID\":\"0\",\"smsNotificationType\":\"0\",\"useTemplate\":\"true\",\"userDescription\":\"\",\"value\":\"0\",\"value2\":\"0\"},\"actions\":{\"close\":0,\"open\":0,\"reconfigure\":0,\"reset\":0,\"sceneActivationSet\":0,\"setValue\":1,\"setValue2\":1,\"startLevelDecrease\":0,\"startLevelIncrease\":0,\"stop\":0,\"stopLevelChange\":0},\"created\":1516643105,\"modified\":1516643105,\"sortOrder\":13},{\"id\":74,\"name\":\"Fenster links\",\"roomID\":14,\"type\":\"com.fibaro.FGRM222\",\"baseType\":\"com.fibaro.FGR\",\"enabled\":true,\"visible\":true,\"isPlugin\":false,\"parentId\":73,\"remoteGatewayId\":0,\"viewXml\":false,\"configXml\":false,\"interfaces\":[\"energy\",\"levelChange\",\"power\",\"zwave\",\"zwaveMultiChannelAssociation\",\"zwaveProtection\",\"zwaveSceneActivation\"],\"properties\":{\"pollingTimeSec\":0,\"zwaveCompany\":\"Fibargroup\",\"zwaveInfo\":\"3,3,52\",\"zwaveVersion\":\"25.25\",\"RFProtectionState\":\"0\",\"RFProtectionSupport\":\"3\",\"configured\":true,\"dead\":\"false\",\"deviceControlType\":\"54\",\"deviceIcon\":\"87\",\"emailNotificationID\":\"0\",\"emailNotificationType\":\"0\",\"endPointId\":\"0\",\"energy\":\"0.64\",\"liliOffCommand\":\"\",\"liliOnCommand\":\"\",\"localProtectionState\":\"0\",\"localProtectionSupport\":\"5\",\"log\":\"\",\"logTemp\":\"\",\"manufacturer\":\"\",\"markAsDead\":\"true\",\"model\":\"\",\"nodeId\":\"21\",\"parametersTemplate\":\"721\",\"power\":\"0.00\",\"productInfo\":\"1,15,3,2,16,0" +
|
||||
",25,25\",\"protectionExclusiveControl\":\"0\",\"protectionExclusiveControlSupport\":\"false\",\"protectionLocal\":\"0\",\"protectionLocalSupport\":\"5\",\"protectionRF\":\"0\",\"protectionRFSupport\":\"3\",\"protectionState\":\"0\",\"protectionTimeout\":\"0\",\"protectionTimeoutSupport\":\"false\",\"pushNotificationID\":\"0\",\"pushNotificationType\":\"0\",\"remoteGatewayId\":\"0\",\"saveLogs\":\"true\",\"sceneActivation\":\"0\",\"serialNumber\":\"\",\"showEnergy\":\"true\",\"smsNotificationID\":\"0\",\"smsNotificationType\":\"0\",\"useTemplate\":\"true\",\"userDescription\":\"\",\"value\":\"0\",\"value2\":\"0\"},\"actions\":{\"close\":0,\"open\":0,\"reconfigure\":0,\"reset\":0,\"sceneActivationSet\":0,\"setValue\":1,\"setValue2\":1,\"startLevelDecrease\":0,\"startLevelIncrease\":0,\"stop\":0,\"stopLevelChange\":0},\"created\":1516643106,\"modified\":1516643106,\"sortOrder\":14},{\"id\":77,\"name\":\"Fenster Sideboard\",\"roomID\":14,\"type\":\"com.fibaro.FGRM222\",\"baseType\":\"com.fibaro.FGR\",\"enabled\":true,\"visible\":true,\"isPlugin\":false,\"parentId\":76,\"remoteGatewayId\":0,\"viewXml\":false,\"configXml\":false,\"interfaces\":[\"energy\",\"levelChange\",\"power\",\"zwave\",\"zwaveMultiChannelAssociation\",\"zwaveProtection\",\"zwaveSceneActivation\"],\"properties\":{\"pollingTimeSec\":0,\"zwaveCompany\":\"Fibargroup\",\"zwaveInfo\":\"3,3,52\",\"zwaveVersion\":\"25.25\",\"RFProtectionState\":\"0\",\"RFProtectionSupport\":\"3\",\"configured\":true,\"dead\":\"false\",\"deviceControlType\":\"54\",\"deviceIcon\":\"87\",\"emailNotificationID\":\"0\",\"emailNotificationType\":\"0\",\"endPointId\":\"0\",\"energy\":\"0.63\",\"liliOffCommand\":\"\",\"liliOnCommand\":\"\",\"localProtectionState\":\"0\",\"localProtectionSupport\":\"5\",\"log\":\"\",\"logTemp\":\"\",\"manufacturer\":\"\",\"markAsDead\":\"true\",\"model\":\"\",\"nodeId\":\"22\",\"parametersTemplate\":\"721\",\"power\":\"0.00\",\"productInfo\":\"1,15,3,2,16,0,25,25\",\"protectionExclusiveControl\":\"0\",\"protectionExclusiveControlSupport\":\"false\",\"protectionLocal\":\"0\",\"protectionLocalSupport\":\"5\",\"protectionRF\":\"0\",\"protectionRFSupport\":\"3\",\"protectionState\":\"0\",\"protectionTimeout\":\"0\",\"protectionTimeoutSupport\":\"false\",\"pushNotificationID\":\"0\",\"pushNotificationType\":\"0\",\"remoteGatewayId\":\"0\",\"saveLogs\":\"true\",\"sceneAc" +
|
||||
"tivation\":\"0\",\"serialNumber\":\"\",\"showEnergy\":\"true\",\"smsNotificationID\":\"0\",\"smsNotificationType\":\"0\",\"useTemplate\":\"true\",\"userDescription\":\"\",\"value\":\"0\",\"value2\":\"0\"},\"actions\":{\"close\":0,\"open\":0,\"reconfigure\":0,\"reset\":0,\"sceneActivationSet\":0,\"setValue\":1,\"setValue2\":1,\"startLevelDecrease\":0,\"startLevelIncrease\":0,\"stop\":0,\"stopLevelChange\":0},\"created\":1516643106,\"modified\":1516643106,\"sortOrder\":15},{\"id\":112,\"name\":\"Stehlampe\",\"roomID\":12,\"type\":\"com.fibaro.multilevelSwitch\",\"baseType\":\"com.fibaro.binarySwitch\",\"enabled\":true,\"visible\":true,\"isPlugin\":false,\"parentId\":111,\"remoteGatewayId\":0,\"viewXml\":false,\"configXml\":false,\"interfaces\":[\"deviceGrouping\",\"fibaroFirmwareUpdate\",\"levelChange\",\"light\",\"zwave\",\"zwaveSwitchAll\"],\"properties\":{\"pollingTimeSec\":0,\"zwaveCompany\":\"Domitech Products\",\"zwaveInfo\":\"3,4,5\",\"zwaveVersion\":\"5.14\",\"configured\":true,\"dead\":\"false\",\"deviceControlType\":\"23\",\"deviceGroup\":\"[]\",\"deviceGroupMaster\":\"0\",\"deviceIcon\":\"15\",\"emailNotificationID\":\"0\",\"emailNotificationType\":\"0\",\"endPointId\":\"0\",\"firmwareUpdate\":\"{\\\"info\\\":\\\"\\\",\\\"progress\\\":0,\\\"status\\\":\\\"UpToDate\\\",\\\"updateVersion\\\":\\\"5.14\\\"}\",\"isLight\":\"true\",\"liliOffCommand\":\"\",\"liliOnCommand\":\"\",\"log\":\"\",\"logTemp\":\"\",\"manufacturer\":\"\",\"markAsDead\":\"true\",\"model\":\"\",\"nodeId\":\"27\",\"parametersTemplate\":\"807\",\"productInfo\":\"2,14,76,66,49,52,5,14\",\"pushNotificationID\":\"0\",\"pushNotificationType\":\"0\",\"remoteGatewayId\":\"0\",\"saveLogs\":\"true\",\"serialNumber\":\"\",\"smsNotificationID\":\"0\",\"smsNotificationType\":\"0\",\"switchAllMode\":\"SWITCH_ALL_INCLUDED_IN_THE_ALL_ON_ALL_OFF_FUNCTIONALITY\",\"updateVersion\":\"\",\"useTemplate\":\"true\",\"userDescription\":\"\",\"value\":\"0\"},\"actions\":{\"abortUpdate\":1,\"reconfigure\":0,\"retryUpdate\":1,\"setValue\":1,\"startLevelDecrease\":0,\"startLevelIncrease\":0,\"startUpdate\":1,\"stopLevelChange\":0,\"turnOff\":0,\"turnOn\":0,\"updateFirmware\":1},\"created\":1516643107,\"modified\":1516643107,\"sortOrder\":6},{\"id\":114,\"name\":\"RGBW\",\"roomID\":12,\"type\":\"com.fibaro.FGRGBW441M\",\"baseType\":\"com.fibaro.colorController\",\"enabled\":true,\"visible\":tr" +
|
||||
"ue,\"isPlugin\":false,\"parentId\":113,\"remoteGatewayId\":0,\"viewXml\":false,\"configXml\":false,\"interfaces\":[\"deviceGrouping\",\"energy\",\"fibaroFirmwareUpdate\",\"levelChange\",\"light\",\"power\",\"zwave\",\"zwaveSwitchAll\"],\"properties\":{\"pollingTimeSec\":0,\"zwaveCompany\":\"Fibargroup\",\"zwaveInfo\":\"3,3,52\",\"zwaveVersion\":\"26.25\",\"associationMode\":\"0\",\"brightness\":\"0\",\"buttonType\":\"0\",\"color\":\"0,0,0,0\",\"configured\":true,\"currentProgram\":\"0\",\"currentProgramID\":\"0\",\"dead\":\"false\",\"deviceControlType\":\"50\",\"deviceGroup\":\"[]\",\"deviceGroupMaster\":\"0\",\"deviceIcon\":\"15\",\"emailNotificationID\":\"0\",\"emailNotificationType\":\"0\",\"endPointId\":\"0\",\"energy\":\"1.72\",\"favoriteProgram\":\"0\",\"firmwareUpdate\":\"{\\\"info\\\":\\\"\\\",\\\"progress\\\":0,\\\"status\\\":\\\"UpToDate\\\",\\\"updateVersion\\\":\\\"26.25\\\"}\",\"isLight\":\"true\",\"lastColorSet\":\"0,0,0,0\",\"liliOffCommand\":\"\",\"liliOnCommand\":\"\",\"log\":\"\",\"logTemp\":\"\",\"manufacturer\":\"\",\"markAsDead\":\"true\",\"mode\":\"0\",\"model\":\"\",\"nodeId\":\"28\",\"parametersTemplate\":\"231\",\"power\":\"0.00\",\"productInfo\":\"1,15,9,0,16,0,26,25\",\"programsSortOrder\":\"1,2,3,4,5\",\"pushNotificationID\":\"0\",\"pushNotificationType\":\"0\",\"rememberColor\":\"false\",\"remoteGatewayId\":\"0\",\"saveLogs\":\"true\",\"serialNumber\":\"\",\"showEnergy\":\"true\",\"smsNotificationID\":\"0\",\"smsNotificationType\":\"0\",\"switchAllMode\":\"SWITCH_ALL_INCLUDED_IN_THE_ALL_ON_ALL_OFF_FUNCTIONALITY\",\"updateVersion\":\"\",\"useTemplate\":\"true\",\"userDescription\":\"\",\"value\":\"0\"},\"actions\":{\"abortUpdate\":1,\"reconfigure\":0,\"reset\":0,\"retryUpdate\":1,\"setB\":1,\"setBrightness\":1,\"setColor\":1,\"setFavoriteProgram\":2,\"setG\":1,\"setR\":1,\"setValue\":1,\"setW\":1,\"startLevelDecrease\":0,\"startLevelIncrease\":0,\"startProgram\":1,\"startUpdate\":1,\"stopLevelChange\":0,\"turnOff\":0,\"turnOn\":0,\"updateFirmware\":1},\"created\":1516643107,\"modified\":1516643107,\"sortOrder\":7},{\"id\":122,\"name\":\"Fenster\",\"roomID\":12,\"type\":\"com.fibaro.FGRM222\",\"baseType\":\"com.fibaro.FGR\",\"enabled\":true,\"visible\":true,\"isPlugin\":false,\"parentId\":121,\"remoteGatewayId\":0,\"viewXml\":false,\"configXml\":false,\"interfaces\":[\"energy\",\"fibaroFirmwareUpdate\",\"levelChange\",\"powe" +
|
||||
"r\",\"zwave\",\"zwaveConfiguration\",\"zwaveProtection\",\"zwaveSceneActivation\"],\"properties\":{\"pollingTimeSec\":0,\"zwaveCompany\":\"Fibargroup\",\"zwaveInfo\":\"3,3,52\",\"zwaveVersion\":\"24.24\",\"RFProtectionState\":\"0\",\"RFProtectionSupport\":\"3\",\"configured\":true,\"dead\":\"false\",\"deviceControlType\":\"54\",\"deviceIcon\":\"87\",\"emailNotificationID\":\"0\",\"emailNotificationType\":\"0\",\"endPointId\":\"0\",\"energy\":\"0.17\",\"firmwareUpdate\":\"{\\\"info\\\":\\\"\\\",\\\"progress\\\":0,\\\"status\\\":\\\"UpToDate\\\",\\\"updateVersion\\\":\\\"24.24\\\"}\",\"liliOffCommand\":\"\",\"liliOnCommand\":\"\",\"localProtectionState\":\"0\",\"localProtectionSupport\":\"5\",\"log\":\"\",\"logTemp\":\"\",\"manufacturer\":\"\",\"markAsDead\":\"true\",\"model\":\"\",\"nodeId\":\"29\",\"parametersTemplate\":\"249\",\"power\":\"0.00\",\"productInfo\":\"1,15,3,1,16,1,24,24\",\"protectionExclusiveControl\":\"0\",\"protectionExclusiveControlSupport\":\"false\",\"protectionState\":\"0\",\"protectionTimeout\":\"0\",\"protectionTimeoutSupport\":\"false\",\"pushNotificationID\":\"0\",\"pushNotificationType\":\"0\",\"remoteGatewayId\":\"0\",\"saveLogs\":\"true\",\"sceneActivation\":\"0\",\"serialNumber\":\"\",\"showEnergy\":\"true\",\"smsNotificationID\":\"0\",\"smsNotificationType\":\"0\",\"updateVersion\":\"\",\"useTemplate\":\"true\",\"userDescription\":\"\",\"value\":\"0\",\"value2\":\"0\"},\"actions\":{\"abortUpdate\":1,\"close\":0,\"getParameter\":1,\"open\":0,\"reconfigure\":0,\"reset\":0,\"retryUpdate\":1,\"sceneActivationSet\":0,\"setParameter\":2,\"setValue\":1,\"setValue2\":1,\"startLevelDecrease\":0,\"startLevelIncrease\":0,\"startUpdate\":1,\"stop\":0,\"stopLevelChange\":0,\"updateFirmware\":1},\"created\":1516643108,\"modified\":1516643108,\"sortOrder\":16}]";
|
||||
|
||||
public final static String RoomTestData = "[{\"id\":4,\"name\":\"Dachboden\",\"sectionID\":4,\"icon\":\"room_bedroom\",\"defaultSensors\":{\"temperature\":0,\"humidity\":0,\"light\":0},\"defaultThermostat\":0,\"sortOrder\":1},{\"id\":5,\"name\":\"Badezimmer\",\"sectionID\":5,\"icon\":\"room_wanna\",\"defaultSensors\":{\"temperature\":0,\"humidity\":0,\"light\":0},\"defaultThermostat\":0,\"sortOrder\":2},{\"id\":6,\"name\":\"Büro\",\"sectionID\":5,\"icon\":\"room_office\",\"defaultSensors\":{\"temperature\":0,\"humidity\":0,\"light\":0},\"defaultThermostat\":0,\"sortOrder\":3},{\"id\":7,\"name\":\"Flur\",\"sectionID\":5,\"icon\":\"room_schody2\",\"defaultSensors\":{\"temperature\":0,\"humidity\":0,\"light\":0},\"defaultThermostat\":0,\"sortOrder\":4},{\"id\":8,\"name\":\"Schlafzimmer\",\"sectionID\":5,\"icon\":\"room_bedroom\",\"defaultSensors\":{\"temperature\":0,\"humidity\":0,\"light\":0},\"defaultThermostat\":0,\"sortOrder\":5},{\"id\":9,\"name\":\"Emelie\",\"sectionID\":5,\"icon\":\"room_wardrobe\",\"defaultSensors\":{\"temperature\":0,\"humidity\":0,\"light\":0},\"defaultThermostat\":0,\"sortOrder\":6},{\"id\":10,\"name\":\"Mino\",\"sectionID\":5,\"icon\":\"room_garage\",\"defaultSensors\":{\"temperature\":0,\"humidity\":0,\"light\":0},\"defaultThermostat\":0,\"sortOrder\":7},{\"id\":11,\"name\":\"Flur\",\"sectionID\":6,\"icon\":\"room_drzwiwejsciowe\",\"defaultSensors\":{\"temperature\":181,\"humidity\":0,\"light\":182},\"defaultThermostat\":0,\"sortOrder\":8},{\"id\":12,\"name\":\"Wohnzimmer\",\"sectionID\":6,\"icon\":\"room_sofa\",\"defaultSensors\":{\"temperature\":0,\"humidity\":0,\"light\":0},\"defaultThermostat\":0,\"sortOrder\":9},{\"id\":13,\"name\":\"Küche\",\"sectionID\":6,\"icon\":\"room_dining\",\"defaultSensors\":{\"temperature\":0,\"humidity\":0,\"light\":0},\"defaultThermostat\":0,\"sortOrder\":10},{\"id\":14,\"name\":\"Esszimmer\",\"sectionID\":6,\"icon\":\"room_jadalnia\",\"defaultSensors\":{\"temperature\":0,\"humidity\":0,\"light\":0},\"defaultThermostat\":0,\"sortOrder\":11},{\"id\":15,\"name\":\"HWR\",\"sectionID\":6,\"icon\":\"room_laundry\",\"defaultSensors\":{\"temperature\":0,\"humidity\":0,\"light\":0},\"defaultThermostat\":0,\"sortOrder\":12},{\"id\":16,\"name\":\"Gäste WC\",\"sectionID\":6," +
|
||||
"\"icon\":\"room_toilet\",\"defaultSensors\":{\"temperature\":0,\"humidity\":0,\"light\":0},\"defaultThermostat\":0,\"sortOrder\":13},{\"id\":17,\"name\":\"Haus\",\"sectionID\":7,\"icon\":\"room_bedroom\",\"defaultSensors\":{\"temperature\":0,\"humidity\":0,\"light\":0},\"defaultThermostat\":0,\"sortOrder\":14},{\"id\":18,\"name\":\"Terrasse\",\"sectionID\":7,\"icon\":\"room_bedroom\",\"defaultSensors\":{\"temperature\":0,\"humidity\":0,\"light\":0},\"defaultThermostat\":0,\"sortOrder\":15}]";
|
||||
|
||||
public final static String SceneTestData = "[" +
|
||||
"{\"id\":33,\"name\":\"Fernsehlicht aus\",\"type\":\"com.fibaro.luaScene\",\"roomID\":12,\"iconID\":6,\"runConfig\":\"MANUAL_ONLY\",\"alexaProhibited\":true,\"autostart\":true,\"protectedByPIN\":false,\"killable\":true,\"killOtherInstances\":false,\"maxRunningInstances\":4,\"runningInstances\":0,\"instances\":[],\"runningManualInstances\":0,\"visible\":true,\"isLua\":true,\"properties\":\"\",\"triggers\":{\"properties\":[],\"globals\":[],\"events\":[],\"weather\":[]},\"actions\":{\"devices\":[],\"scenes\":[],\"groups\":[]},\"liliStartCommand\":\"\",\"liliStopCommand\":\"\",\"sortOrder\":17}," +
|
||||
"{\"id\":68,\"name\":\"Rollos runterfahren\",\"type\":\"com.fibaro.luaScene\",\"roomID\":14,\"iconID\":6,\"runConfig\":\"MANUAL_ONLY\",\"alexaProhibited\":true,\"autostart\":false,\"protectedByPIN\":false,\"killable\":true,\"killOtherInstances\":false,\"maxRunningInstances\":2,\"runningInstances\":0,\"instances\":[],\"runningManualInstances\":0,\"visible\":true,\"isLua\":true,\"properties\":\"\",\"triggers\":{\"properties\":[],\"globals\":[],\"events\":[],\"weather\":[]},\"actions\":{\"devices\":[],\"scenes\":[],\"groups\":[]},\"liliStartCommand\":\"\",\"liliStopCommand\":\"\",\"sortOrder\":8}," +
|
||||
"{\"id\":69,\"name\":\"Rollos hochfahren\",\"type\":\"com.fibaro.luaScene\",\"roomID\":14,\"iconID\":6,\"runConfig\":\"MANUAL_ONLY\",\"alexaProhibited\":true,\"autostart\":false,\"protectedByPIN\":false,\"killable\":true,\"killOtherInstances\":false,\"maxRunningInstances\":2,\"runningInstances\":0,\"instances\":[],\"runningManualInstances\":0,\"visible\":true,\"isLua\":true,\"properties\":\"\",\"triggers\":{\"properties\":[],\"globals\":[],\"events\":[],\"weather\":[]},\"actions\":{\"devices\":[],\"scenes\":[],\"groups\":[]},\"liliStartCommand\":\"\",\"liliStopCommand\":\"\",\"sortOrder\":9}," +
|
||||
"{\"id\":93,\"name\":\"Alles aus Haus\",\"type\":\"com.fibaro.magicScene\",\"roomID\":12,\"runConfig\":\"TRIGGER_AND_MANUAL\",\"alexaProhibited\":false,\"autostart\":false,\"protectedByPIN\":false,\"killable\":true,\"killOtherInstances\":false,\"maxRunningInstances\":2,\"runningInstances\":0,\"instances\":[],\"runningManualInstances\":0,\"visible\":false,\"properties\":\"{\\\"conditionDeviceId\\\":163,\\\"conditionObjectType\\\":\\\"device\\\",\\\"conditionId\\\":\\\"condition_centralSceneEvent1HeldDown_163\\\",\\\"conditionLua\\\":\\\"true\\\",\\\"conditionValue\\\":\\\"\\\",\\\"conditionRooms\\\":[],\\\"trigger\\\":\\\"163 CentralSceneEvent 1 HeldDown\\\\n163 CentralSceneEvent 1 Released\\\",\\\"actionDeviceId\\\":92,\\\"actionObjectType\\\":\\\"scene\\\",\\\"actionId\\\":\\\"action_runScene_92\\\",\\\"actionLua\\\":\\\"fibaro:startScene(92);\\\",\\\"actionValue\\\":\\\"\\\",\\\"actionRooms\\\":[],\\\"looping\\\":false}\",\"triggers\":{\"properties\":[],\"globals\":[],\"events\":[{\"deviceId\":163,\"eventName\":\"CentralSceneEvent\",\"args\":[\"1\",\"Released\"]}],\"weather\":[]},\"actions\":{\"devices\":[],\"scenes\":[92],\"groups\":[]},\"liliStartCommand\":\"\",\"liliStopCommand\":\"\",\"sortOrder\":18}," +
|
||||
"{\"id\":94,\"name\":\"Fernsehlicht an\",\"type\":\"com.fibaro.blockScene\",\"roomID\":12,\"iconID\":5,\"runConfig\":\"MANUAL_ONLY\",\"alexaProhibited\":false,\"autostart\":true,\"protectedByPIN\":false,\"killable\":true,\"killOtherInstances\":false,\"maxRunningInstances\":2,\"runningInstances\":0,\"instances\":[],\"runningManualInstances\":0,\"visible\":true,\"isLua\":false,\"properties\":\"\",\"triggers\":{\"properties\":[],\"globals\":[],\"events\":[],\"weather\":[]},\"actions\":{\"devices\":[112,114],\"scenes\":[],\"groups\":[]},\"liliStartCommand\":\"\",\"liliStopCommand\":\"\",\"sortOrder\":10}," +
|
||||
"{\"id\":95,\"name\":\"Fernsehlicht + aus\",\"type\":\"com.fibaro.blockScene\",\"roomID\":12,\"iconID\":5,\"runConfig\":\"MANUAL_ONLY\",\"alexaProhibited\":false,\"autostart\":true,\"protectedByPIN\":false,\"killable\":true,\"killOtherInstances\":false,\"maxRunningInstances\":2,\"runningInstances\":0,\"instances\":[],\"runningManualInstances\":0,\"visible\":true,\"isLua\":false,\"properties\":\"\",\"triggers\":{\"properties\":[],\"globals\":[],\"events\":[],\"weather\":[]},\"actions\":{\"devices\":[7,10,11,12,13,14,57,60,74,77,97,112,114],\"scenes\":[],\"groups\":[]},\"liliStartCommand\":\"\",\"liliStopCommand\":\"\",\"sortOrder\":19}," +
|
||||
"{\"id\":96,\"name\":\"Fernsehlicht Wohnzim\",\"type\":\"com.fibaro.magicScene\",\"roomID\":12,\"runConfig\":\"TRIGGER_AND_MANUAL\",\"alexaProhibited\":false,\"autostart\":false,\"protectedByPIN\":false,\"killable\":true,\"killOtherInstances\":false,\"maxRunningInstances\":2,\"runningInstances\":0,\"instances\":[],\"runningManualInstances\":0,\"visible\":false,\"properties\":\"{\\\"conditionDeviceId\\\":163,\\\"conditionObjectType\\\":\\\"device\\\",\\\"conditionId\\\":\\\"condition_centralSceneEvent2Pressed_163\\\",\\\"conditionLua\\\":\\\"true\\\",\\\"conditionValue\\\":\\\"\\\",\\\"conditionRooms\\\":[],\\\"trigger\\\":\\\"163 CentralSceneEvent 2 Pressed\\\",\\\"actionDeviceId\\\":94,\\\"actionObjectType\\\":\\\"scene\\\",\\\"actionId\\\":\\\"action_runScene_94\\\",\\\"actionLua\\\":\\\"fibaro:startScene(94);\\\",\\\"actionValue\\\":\\\"\\\",\\\"actionRooms\\\":[],\\\"looping\\\":false}\",\"triggers\":{\"properties\":[],\"globals\":[],\"events\":[{\"deviceId\":163,\"eventName\":\"CentralSceneEvent\",\"args\":[\"2\",\"Pressed\"]}],\"weather\":[]},\"actions\":{\"devices\":[],\"scenes\":[94],\"groups\":[]},\"liliStartCommand\":\"\",\"liliStopCommand\":\"\",\"sortOrder\":20}," +
|
||||
"{\"id\":98,\"name\":\"Fersehlicht blau\",\"type\":\"com.fibaro.blockScene\",\"roomID\":12,\"iconID\":5,\"runConfig\":\"MANUAL_ONLY\",\"alexaProhibited\":false,\"autostart\":true,\"protectedByPIN\":false,\"killable\":true,\"killOtherInstances\":false,\"maxRunningInstances\":2,\"runningInstances\":0,\"instances\":[],\"runningManualInstances\":0,\"visible\":true,\"isLua\":false,\"properties\":\"\",\"triggers\":{\"properties\":[],\"globals\":[],\"events\":[],\"weather\":[]},\"actions\":{\"devices\":[112,114],\"scenes\":[],\"groups\":[]},\"liliStartCommand\":\"\",\"liliStopCommand\":\"\",\"sortOrder\":11}," +
|
||||
"{\"id\":99,\"name\":\"Fernsehlicht blau+au\",\"type\":\"com.fibaro.blockScene\",\"roomID\":12,\"iconID\":5,\"runConfig\":\"MANUAL_ONLY\",\"alexaProhibited\":false,\"autostart\":true,\"protectedByPIN\":false,\"killable\":true,\"killOtherInstances\":false,\"maxRunningInstances\":2,\"runningInstances\":0,\"instances\":[],\"runningManualInstances\":0,\"visible\":true,\"isLua\":false,\"properties\":\"\",\"triggers\":{\"properties\":[],\"globals\":[],\"events\":[],\"weather\":[]},\"actions\":{\"devices\":[7,10,11,12,13,14,112,114],\"scenes\":[],\"groups\":[]},\"liliStartCommand\":\"\",\"liliStopCommand\":\"\",\"sortOrder\":21}," +
|
||||
"{\"id\":100,\"name\":\"Fernsehlicht blau+au\",\"type\":\"com.fibaro.magicScene\",\"roomID\":12,\"runConfig\":\"TRIGGER_AND_MANUAL\",\"alexaProhibited\":false,\"autostart\":false,\"protectedByPIN\":false,\"killable\":true,\"killOtherInstances\":false,\"maxRunningInstances\":2,\"runningInstances\":0,\"instances\":[],\"runningManualInstances\":0,\"visible\":false,\"properties\":\"{\\\"conditionDeviceId\\\":163,\\\"conditionObjectType\\\":\\\"device\\\",\\\"conditionId\\\":\\\"condition_centralSceneEvent3HeldDown_163\\\",\\\"conditionLua\\\":\\\"true\\\",\\\"conditionValue\\\":\\\"\\\",\\\"conditionRooms\\\":[],\\\"trigger\\\":\\\"163 CentralSceneEvent 3 HeldDown\\\\n163 CentralSceneEvent 3 Released\\\",\\\"actionDeviceId\\\":99,\\\"actionObjectType\\\":\\\"scene\\\",\\\"actionId\\\":\\\"action_runScene_99\\\",\\\"actionLua\\\":\\\"fibaro:startScene(99);\\\",\\\"actionValue\\\":\\\"\\\",\\\"actionRooms\\\":[],\\\"looping\\\":false}\",\"triggers\":{\"properties\":[],\"globals\":[],\"events\":[{\"deviceId\":163,\"eventName\":\"CentralSceneEvent\",\"args\":[\"3\",\"Released\"]}],\"weather\":[]},\"actions\":{\"devices\":[],\"scenes\":[99],\"groups\":[]},\"liliStartCommand\":\"\",\"liliStopCommand\":\"\",\"sortOrder\":22}," +
|
||||
"{\"id\":101,\"name\":\"Fersehlicht blau Woh\",\"type\":\"com.fibaro.magicScene\",\"roomID\":12,\"runConfig\":\"TRIGGER_AND_MANUAL\",\"alexaProhibited\":false,\"autostart\":false,\"protectedByPIN\":false,\"killable\":true,\"killOtherInstances\":false,\"maxRunningInstances\":2,\"runningInstances\":0,\"instances\":[],\"runningManualInstances\":0,\"visible\":false,\"properties\":\"{\\\"conditionDeviceId\\\":163,\\\"conditionObjectType\\\":\\\"device\\\",\\\"conditionId\\\":\\\"condition_centralSceneEvent3Pressed_163\\\",\\\"conditionLua\\\":\\\"true\\\",\\\"conditionValue\\\":\\\"\\\",\\\"conditionRooms\\\":[],\\\"trigger\\\":\\\"163 CentralSceneEvent 3 Pressed\\\",\\\"actionDeviceId\\\":98,\\\"actionObjectType\\\":\\\"scene\\\",\\\"actionId\\\":\\\"action_runScene_98\\\",\\\"actionLua\\\":\\\"fibaro:startScene(98);\\\",\\\"actionValue\\\":\\\"\\\",\\\"actionRooms\\\":[],\\\"looping\\\":false}\",\"triggers\":{\"properties\":[],\"globals\":[],\"events\":[{\"deviceId\":163,\"eventName\":\"CentralSceneEvent\",\"args\":[\"3\",\"Pressed\"]}],\"weather\":[]},\"actions\":{\"devices\":[],\"scenes\":[98],\"groups\":[]},\"liliStartCommand\":\"\",\"liliStopCommand\":\"\",\"sortOrder\":23}" +
|
||||
"]";
|
||||
|
||||
public final static String CallActionTestData = "Fiabro action received";
|
||||
public final static String SceneControlTestData = "Fiabro scene control received";
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro.json;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class Device {
|
||||
private String roomName;
|
||||
|
||||
@SerializedName("id")
|
||||
private String id;
|
||||
|
||||
@SerializedName("name")
|
||||
private String name;
|
||||
|
||||
@SerializedName("roomID")
|
||||
private int roomID;
|
||||
|
||||
@SerializedName("type")
|
||||
private String type;
|
||||
|
||||
@SerializedName("properties")
|
||||
private DeviceProperties properties;
|
||||
|
||||
public String getRoomName() {
|
||||
return roomName;
|
||||
}
|
||||
|
||||
public void setRoomName(String roomName) {
|
||||
this.roomName = roomName;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getRoomID() {
|
||||
return roomID;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public DeviceProperties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public boolean isThermostat() {
|
||||
return type.equals("com.fibaro.setPoint") || type.equals("com.fibaro.thermostatDanfoss")
|
||||
|| type.equals("com.fibaro.thermostatHorstmann");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{" + id + ", " + name + "}";
|
||||
}
|
||||
|
||||
public String fibaroaddress;
|
||||
public String fibaroport;
|
||||
public String fibaroAuth;
|
||||
public String fibaroname;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro.json;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class DeviceProperties {
|
||||
@SerializedName("value")
|
||||
private String value;
|
||||
|
||||
@SerializedName("saveLogs")
|
||||
private String saveLogs;
|
||||
|
||||
@SerializedName("userDescription")
|
||||
private String userDescription;
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
public String getSaveLogs() {
|
||||
return saveLogs;
|
||||
}
|
||||
public String getUserDescription() {
|
||||
return userDescription;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro.json;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class Room {
|
||||
@SerializedName("id")
|
||||
private int id;
|
||||
|
||||
@SerializedName("name")
|
||||
private String name;
|
||||
|
||||
@SerializedName("sectionID")
|
||||
private int sectionID;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getSectionID()
|
||||
{
|
||||
return sectionID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro.json;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class Scene {
|
||||
private String roomName;
|
||||
|
||||
@SerializedName("id")
|
||||
private String id;
|
||||
|
||||
@SerializedName("name")
|
||||
private String name;
|
||||
|
||||
@SerializedName("type")
|
||||
private String type;
|
||||
|
||||
@SerializedName("roomID")
|
||||
private int roomID;
|
||||
|
||||
@SerializedName("liliStartCommand")
|
||||
private String liliStartCommand;
|
||||
|
||||
public String getRoomName() {
|
||||
return roomName;
|
||||
}
|
||||
|
||||
public void setRoomName(String roomName) {
|
||||
this.roomName = roomName;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getRoomID() {
|
||||
return roomID;
|
||||
}
|
||||
|
||||
public String getLiliStartCommand()
|
||||
{
|
||||
return liliStartCommand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{" + id + ", " + name + "}";
|
||||
}
|
||||
|
||||
public String fibaroaddress;
|
||||
public String fibaroport;
|
||||
public String fibaroAuth;
|
||||
public String fibaroname;
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
package com.bwssystems.HABridge.plugins.hal;
|
||||
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
|
||||
public class HalDevice {
|
||||
private String haldevicetype;
|
||||
private String haldevicename;
|
||||
private String haladdress;
|
||||
private String halname;
|
||||
private NamedIP haladdress;
|
||||
private DeviceElements buttons;
|
||||
public String getHaldevicetype() {
|
||||
return haldevicetype;
|
||||
@@ -18,18 +19,12 @@ public class HalDevice {
|
||||
public void setHaldevicename(String haldevicename) {
|
||||
this.haldevicename = haldevicename;
|
||||
}
|
||||
public String getHaladdress() {
|
||||
public NamedIP getHaladdress() {
|
||||
return haladdress;
|
||||
}
|
||||
public void setHaladdress(String haladdress) {
|
||||
public void setHaladdress(NamedIP haladdress) {
|
||||
this.haladdress = haladdress;
|
||||
}
|
||||
public String getHalname() {
|
||||
return halname;
|
||||
}
|
||||
public void setHalname(String halname) {
|
||||
this.halname = halname;
|
||||
}
|
||||
public DeviceElements getButtons() {
|
||||
return buttons;
|
||||
}
|
||||
|
||||
@@ -13,24 +13,34 @@ import com.bwssystems.HABridge.BridgeSettings;
|
||||
import com.bwssystems.HABridge.Home;
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.api.hue.HueError;
|
||||
import com.bwssystems.HABridge.api.hue.HueErrorResponse;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class HalHome implements Home {
|
||||
private static final Logger log = LoggerFactory.getLogger(HalHome.class);
|
||||
private Map<String, HalInfo> hals;
|
||||
private Boolean validHal;
|
||||
private boolean closed;
|
||||
|
||||
public HalHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItems(String type) {
|
||||
if(!validHal)
|
||||
return null;
|
||||
log.debug("consolidating devices for hues");
|
||||
log.debug("consolidating devices for HALs");
|
||||
List<HalDevice> theResponse = null;
|
||||
Iterator<String> keys = hals.keySet().iterator();
|
||||
List<HalDevice> deviceList = new ArrayList<HalDevice>();
|
||||
@@ -103,11 +113,71 @@ public class HalHome implements Home {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
// Not a device handler
|
||||
return null;
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
boolean halFound = false;
|
||||
String responseString = null;
|
||||
String theUrl = anItem.getItem().getAsString();
|
||||
if(theUrl != null && !theUrl.isEmpty () && theUrl.contains("http")) {
|
||||
String intermediate = theUrl.substring(theUrl.indexOf("://") + 3);
|
||||
String hostPortion = intermediate.substring(0, intermediate.indexOf('/'));
|
||||
// String theUrlBody = intermediate.substring(intermediate.indexOf('/') + 1);
|
||||
// String hostAddr = null;
|
||||
// String port = null;
|
||||
// if (hostPortion.contains(":")) {
|
||||
// hostAddr = hostPortion.substring(0, intermediate.indexOf(':'));
|
||||
// port = hostPortion.substring(intermediate.indexOf(':') + 1);
|
||||
// } else
|
||||
// hostAddr = hostPortion;
|
||||
log.debug("executing HUE api request to Http "
|
||||
+ (anItem.getHttpVerb() == null ? "GET" : anItem.getHttpVerb()) + ": "
|
||||
+ anItem.getItem().getAsString());
|
||||
|
||||
String anUrl = null;
|
||||
|
||||
anUrl = BrightnessDecode.calculateReplaceIntensityValue(intermediate, intensity, targetBri, targetBriInc, false);
|
||||
anUrl = DeviceDataDecode.replaceDeviceData(anUrl, device);
|
||||
anUrl = TimeDecode.replaceTimeValue(anUrl);
|
||||
|
||||
for (Map.Entry<String, HalInfo> entry : hals.entrySet())
|
||||
{
|
||||
if(entry.getValue().getHalAddress().getIp().equals(hostPortion)) {
|
||||
halFound = true;
|
||||
if(entry.getValue().getHalAddress().getSecure()!= null && entry.getValue().getHalAddress().getSecure())
|
||||
anUrl = "https://" + anUrl;
|
||||
else
|
||||
anUrl = "http://" + anUrl;
|
||||
|
||||
if(!anUrl.contains("?Token="))
|
||||
anUrl = anUrl + "?Token=" + entry.getValue().getHalAddress().getPassword();
|
||||
|
||||
log.debug("executing HUE api request to Http "
|
||||
+ (anItem.getHttpVerb() == null ? "GET" : anItem.getHttpVerb()) + ": "
|
||||
+ anUrl);
|
||||
|
||||
if (entry.getValue().deviceCommand(anUrl) == null) {
|
||||
log.warn("Error on calling hal to change device state: " + anUrl);
|
||||
responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId,
|
||||
"Error on calling url to change device state", "/lights/"
|
||||
+ lightId + "state", null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!halFound) {
|
||||
log.warn("No HAL found to call: " + theUrl);
|
||||
responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId,
|
||||
"No HAL found.", "/lights/"
|
||||
+ lightId + "state", null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
return responseString;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,7 +202,13 @@ public class HalHome implements Home {
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
// noop
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
|
||||
hals = null;
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHome;
|
||||
import com.bwssystems.HABridge.util.TextStringFormatter;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
@@ -35,13 +36,13 @@ public class HalInfo {
|
||||
private static final String IRDATA_TYPE = "IrData";
|
||||
private HTTPHandler httpClient;
|
||||
private NamedIP halAddress;
|
||||
private String theToken;
|
||||
|
||||
public HalInfo(NamedIP addressName, String aGivenToken) {
|
||||
super();
|
||||
httpClient = new HTTPHandler();
|
||||
httpClient = HTTPHome.getHandler();
|
||||
halAddress = addressName;
|
||||
theToken = aGivenToken;
|
||||
if(halAddress.getPassword() == null || halAddress.getPassword().trim().isEmpty())
|
||||
halAddress.setPassword(aGivenToken);
|
||||
}
|
||||
|
||||
public List<HalDevice> getLights() {
|
||||
@@ -98,12 +99,16 @@ public class HalInfo {
|
||||
|
||||
String theUrl = null;
|
||||
String theData;
|
||||
theUrl = "http://" + halAddress.getIp() + apiType + theToken;
|
||||
if(halAddress.getSecure()!= null && halAddress.getSecure())
|
||||
theUrl = "https://";
|
||||
else
|
||||
theUrl = "http://";
|
||||
theUrl = theUrl + halAddress.getIp() + apiType + halAddress.getPassword();
|
||||
theData = httpClient.doHttpRequest(theUrl, null, null, null, null);
|
||||
if(theData != null) {
|
||||
log.debug("GET " + deviceType + " HalApiResponse - data: " + theData);
|
||||
theHalApiResponse = new Gson().fromJson(theData, DeviceElements.class);
|
||||
if(theHalApiResponse.getDeviceElements() == null) {
|
||||
if(theHalApiResponse == null || theHalApiResponse.getDeviceElements() == null) {
|
||||
StatusDescription theStatus = new Gson().fromJson(theData, StatusDescription.class);
|
||||
if(theStatus.getStatus() == null) {
|
||||
log.warn("Cannot get an devices for type " + deviceType + " for hal " + halAddress.getName() + " as response is not parsable.");
|
||||
@@ -121,8 +126,10 @@ public class HalInfo {
|
||||
HalDevice aNewHalDevice = new HalDevice();
|
||||
aNewHalDevice.setHaldevicetype(deviceType);
|
||||
aNewHalDevice.setHaldevicename(theDevice.getDeviceName());
|
||||
aNewHalDevice.setHaladdress(halAddress.getIp());
|
||||
aNewHalDevice.setHalname(halAddress.getName());
|
||||
NamedIP theaddress = new NamedIP();
|
||||
theaddress.setIp(halAddress.getIp());
|
||||
theaddress.setName(halAddress.getName());
|
||||
aNewHalDevice.setHaladdress(theaddress);
|
||||
deviceList.add(aNewHalDevice);
|
||||
|
||||
}
|
||||
@@ -145,7 +152,11 @@ public class HalInfo {
|
||||
deviceList = new ArrayList<HalDevice>();
|
||||
while (theHalDevices.hasNext()) {
|
||||
HalDevice theHalDevice = theHalDevices.next();
|
||||
theUrl = "http://" + halAddress.getIp() + IRBUTTON_REQUEST + TextStringFormatter.forQuerySpaceUrl(theHalDevice.getHaldevicename()) + TOKEN_REQUEST + theToken;
|
||||
if(halAddress.getSecure()!= null && halAddress.getSecure())
|
||||
theUrl = "https://";
|
||||
else
|
||||
theUrl = "http://";
|
||||
theUrl = theUrl + halAddress.getIp() + IRBUTTON_REQUEST + TextStringFormatter.forQuerySpaceUrl(theHalDevice.getHaldevicename()) + TOKEN_REQUEST + halAddress.getPassword();
|
||||
theData = httpClient.doHttpRequest(theUrl, null, null, null, null);
|
||||
if (theData != null) {
|
||||
log.debug("GET IrData for IR Device " + theHalDevice.getHaldevicename() + " HalApiResponse - data: " + theData);
|
||||
@@ -177,6 +188,12 @@ public class HalInfo {
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
public String deviceCommand(String theUrl) {
|
||||
String theData = null;
|
||||
theData = httpClient.doHttpRequest(theUrl, null, null, null, null);
|
||||
return theData;
|
||||
}
|
||||
|
||||
public NamedIP getHalAddress() {
|
||||
return halAddress;
|
||||
}
|
||||
@@ -190,6 +207,5 @@ public class HalInfo {
|
||||
httpClient.closeHandler();
|
||||
httpClient = null;
|
||||
halAddress = null;
|
||||
theToken = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ public class ButtonPress {
|
||||
private Integer delay;
|
||||
private Integer count;
|
||||
private String hub;
|
||||
private Integer pressTime;
|
||||
public String getDevice() {
|
||||
return device;
|
||||
}
|
||||
@@ -43,4 +44,10 @@ public class ButtonPress {
|
||||
public void setHub(String hub) {
|
||||
this.hub = hub;
|
||||
}
|
||||
public Integer getPressTime() {
|
||||
return pressTime;
|
||||
}
|
||||
public void setPressTime(Integer pressTime) {
|
||||
this.pressTime = pressTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import net.whistlingfish.harmony.HarmonyClient;
|
||||
import net.whistlingfish.harmony.config.Activity;
|
||||
import net.whistlingfish.harmony.config.Device;
|
||||
import net.whistlingfish.harmony.config.HarmonyConfig;
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
|
||||
public class HarmonyHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger(HarmonyHandler.class);
|
||||
@@ -16,8 +17,9 @@ public class HarmonyHandler {
|
||||
private Boolean noopCalls;
|
||||
private Boolean devMode;
|
||||
private DevModeResponse devResponse;
|
||||
private NamedIP myNameAndIP;
|
||||
|
||||
public HarmonyHandler(HarmonyClient theClient, Boolean noopCallsSetting, DevModeResponse devResponseSetting) {
|
||||
public HarmonyHandler(HarmonyClient theClient, Boolean noopCallsSetting, DevModeResponse devResponseSetting, NamedIP aNameAndIP) {
|
||||
super();
|
||||
noopCalls = noopCallsSetting;
|
||||
devMode = Boolean.TRUE;
|
||||
@@ -27,6 +29,7 @@ public class HarmonyHandler {
|
||||
else
|
||||
devResponse = devResponseSetting;
|
||||
harmonyClient = theClient;
|
||||
myNameAndIP = aNameAndIP;
|
||||
}
|
||||
|
||||
public List<Activity> getActivities() {
|
||||
@@ -34,7 +37,15 @@ public class HarmonyHandler {
|
||||
if(devMode)
|
||||
return devResponse.getActivities();
|
||||
|
||||
return harmonyClient.getConfig().getActivities();
|
||||
List<Activity> listOfActivities = null;
|
||||
|
||||
try {
|
||||
listOfActivities = harmonyClient.getConfig().getActivities();
|
||||
} catch (RuntimeException e) {
|
||||
handleExceptionError(e);
|
||||
}
|
||||
|
||||
return listOfActivities;
|
||||
}
|
||||
|
||||
public List<Device> getDevices() {
|
||||
@@ -42,7 +53,14 @@ public class HarmonyHandler {
|
||||
if(devMode)
|
||||
return devResponse.getDevices();
|
||||
|
||||
return harmonyClient.getConfig().getDevices();
|
||||
List<Device> listOfDevices = null;
|
||||
|
||||
try {
|
||||
listOfDevices = harmonyClient.getConfig().getDevices();
|
||||
} catch (RuntimeException e) {
|
||||
handleExceptionError(e);
|
||||
}
|
||||
return listOfDevices;
|
||||
}
|
||||
|
||||
public HarmonyConfig getConfig() {
|
||||
@@ -50,19 +68,31 @@ public class HarmonyHandler {
|
||||
if(devMode)
|
||||
return devResponse.getConfig();
|
||||
|
||||
return harmonyClient.getConfig();
|
||||
HarmonyConfig aConfig = null;
|
||||
try {
|
||||
aConfig = harmonyClient.getConfig();
|
||||
} catch (RuntimeException e) {
|
||||
handleExceptionError(e);
|
||||
}
|
||||
return aConfig;
|
||||
}
|
||||
|
||||
public Activity getCurrentActivity() {
|
||||
log.debug("Harmony api current sctivity requested.");
|
||||
if(devMode)
|
||||
return devResponse.getCurrentActivity();
|
||||
|
||||
return harmonyClient.getCurrentActivity();
|
||||
|
||||
Activity anActivity = null;
|
||||
try {
|
||||
anActivity = harmonyClient.getCurrentActivity();
|
||||
} catch (RuntimeException e) {
|
||||
handleExceptionError(e);
|
||||
}
|
||||
return anActivity;
|
||||
}
|
||||
|
||||
public Boolean startActivity(RunActivity anActivity) {
|
||||
log.debug("Harmony api start activity requested for: " + anActivity.getName() + " noop mode: " + noopCalls);
|
||||
log.debug("Harmony api start activity requested for: " + anActivity.getName() + " for a hub: " + anActivity.getHub() + " noop mode: " + noopCalls);
|
||||
if (anActivity.isValid()) {
|
||||
try {
|
||||
if (noopCalls || devMode) {
|
||||
@@ -72,7 +102,7 @@ public class HarmonyHandler {
|
||||
devResponse.setCurrentActivity(devResponse.getConfig().getActivityByName(anActivity.getName()));
|
||||
}
|
||||
|
||||
log.info("noop mode: Harmony api start activity requested for: " + anActivity.getName());
|
||||
log.info("noop mode: Harmony api start activity requested for: " + anActivity.getName() + " for a hub: " + anActivity.getHub());
|
||||
}
|
||||
else
|
||||
harmonyClient.startActivity(Integer.parseInt(anActivity.getName()));
|
||||
@@ -81,12 +111,16 @@ public class HarmonyHandler {
|
||||
if (!noopCalls)
|
||||
harmonyClient.startActivityByName(anActivity.getName());
|
||||
} catch (IllegalArgumentException ei) {
|
||||
log.error("Error in finding activity: " + anActivity.getName());
|
||||
log.error("Error in finding activity: " + anActivity.getName() + " for a hub: " + anActivity.getHub());
|
||||
return false;
|
||||
} catch (RuntimeException e1) {
|
||||
handleExceptionError(e1);
|
||||
}
|
||||
} catch (RuntimeException e1) {
|
||||
handleExceptionError(e1);
|
||||
}
|
||||
} else {
|
||||
log.error("Error in finding activity: " + anActivity.getName());
|
||||
log.error("Error in finding activity: " + anActivity.getName() + " for a hub: " + anActivity.getHub());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -94,32 +128,52 @@ public class HarmonyHandler {
|
||||
}
|
||||
|
||||
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);
|
||||
log.debug("Harmony api press a button requested for device: " + aDeviceButton.getDevice() + " and a for button: " + aDeviceButton.getButton() + " with pressTime of: " + aDeviceButton.getPressTime() + " for a hub: " + aDeviceButton.getHub() + " 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());
|
||||
log.info("noop mode: Harmony api press a button requested for device: " + aDeviceButton.getDevice() + " and a for button: " + aDeviceButton.getButton() +
|
||||
" with a pressTime of: " + aDeviceButton.getPressTime() + " for a hub: " + aDeviceButton.getHub());
|
||||
}
|
||||
else
|
||||
harmonyClient.pressButton(Integer.parseInt(aDeviceButton.getDevice()), aDeviceButton.getButton());
|
||||
|
||||
else {
|
||||
if(aDeviceButton.getPressTime() != null && aDeviceButton.getPressTime() > 0)
|
||||
harmonyClient.pressButton(Integer.parseInt(aDeviceButton.getDevice()), aDeviceButton.getButton(), aDeviceButton.getPressTime());
|
||||
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());
|
||||
log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton() + " for a hub: " + aDeviceButton.getHub());
|
||||
return false;
|
||||
} catch (RuntimeException e1) {
|
||||
handleExceptionError(e1);
|
||||
}
|
||||
} catch (RuntimeException e1) {
|
||||
handleExceptionError(e1);
|
||||
}
|
||||
} else {
|
||||
log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton());
|
||||
log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton() + " for a hub: " + aDeviceButton.getHub());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void handleExceptionError(Exception e) {
|
||||
if(e.getMessage().equalsIgnoreCase("Failed communicating with Harmony Hub")) {
|
||||
log.warn("Issue in communcicating with Harmony Hub, retrying connect....");
|
||||
try {
|
||||
harmonyClient.disconnect();
|
||||
} catch(Exception e1) {
|
||||
log.warn("Hub disconnect failed, continuing....");
|
||||
}
|
||||
harmonyClient.connect(myNameAndIP.getIp());
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
log.debug("Harmony api shutdown requested.");
|
||||
if(devMode)
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
@@ -31,16 +32,24 @@ public class HarmonyHome implements Home {
|
||||
private Boolean isDevMode;
|
||||
private Boolean validHarmony;
|
||||
private Gson aGsonHandler;
|
||||
private boolean closed;
|
||||
|
||||
public HarmonyHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
if(!validHarmony)
|
||||
return;
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
if(isDevMode || hubs == null)
|
||||
return;
|
||||
Iterator<String> keys = hubs.keySet().iterator();
|
||||
@@ -50,6 +59,7 @@ public class HarmonyHome implements Home {
|
||||
}
|
||||
|
||||
hubs = null;
|
||||
closed = true;
|
||||
}
|
||||
|
||||
public HarmonyHandler getHarmonyHandler(String aName) {
|
||||
@@ -125,7 +135,7 @@ public class HarmonyHome implements Home {
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
String responseString = null;
|
||||
log.debug("executing HUE api request to change " + anItem.getType() + " to Harmony: " + device.getName());
|
||||
if(!validHarmony) {
|
||||
@@ -181,7 +191,7 @@ public class HarmonyHome implements Home {
|
||||
aMultiUtil.setTheDelay(anItem.getDelay());
|
||||
else
|
||||
aMultiUtil.setTheDelay(aMultiUtil.getDelayDefault());
|
||||
log.debug("pressing button: " + deviceButtons[z].getDevice() + " - " + deviceButtons[z].getButton() + " - iteration: " + String.valueOf(z) + " - count: " + String.valueOf(y));
|
||||
log.debug("pressing button: " + deviceButtons[z].getDevice() + " - " + deviceButtons[z].getButton() + " with pressTime of: " + deviceButtons[z].getPressTime() + " - iteration: " + String.valueOf(z) + " - count: " + String.valueOf(y));
|
||||
if(deviceButtons[z].getHub() == null || deviceButtons[z].getHub().isEmpty())
|
||||
deviceButtons[z].setHub(device.getTargetDevice());
|
||||
HarmonyHandler myHarmony = getHarmonyHandler(deviceButtons[z].getHub());
|
||||
@@ -259,4 +269,10 @@ public class HarmonyHome implements Home {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
// noop
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import static java.lang.String.format;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHome;
|
||||
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -44,7 +46,7 @@ public class HarmonyServer {
|
||||
dummyProvider = null;
|
||||
myNameAndIP = theHarmonyAddress;
|
||||
isDevMode = false;
|
||||
httpClient = new HTTPHandler();
|
||||
httpClient = HTTPHome.getHandler();
|
||||
}
|
||||
|
||||
public static HarmonyServer setup(
|
||||
@@ -108,7 +110,7 @@ public class HarmonyServer {
|
||||
});
|
||||
harmonyClient.connect(myNameAndIP.getIp());
|
||||
}
|
||||
myHarmony = new HarmonyHandler(harmonyClient, noopCalls, devResponse);
|
||||
myHarmony = new HarmonyHandler(harmonyClient, noopCalls, devResponse, myNameAndIP);
|
||||
}
|
||||
|
||||
public HarmonyHandler getMyHarmony() {
|
||||
|
||||
@@ -15,6 +15,7 @@ import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
@@ -25,10 +26,13 @@ public class HassHome implements Home {
|
||||
private Map<String, HomeAssistant> hassMap;
|
||||
private Boolean validHass;
|
||||
private Gson aGsonHandler;
|
||||
private boolean closed;
|
||||
|
||||
public HassHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,9 +117,14 @@ public class HassHome implements Home {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
String theReturn = null;
|
||||
log.debug("executing HUE api request to send message to HomeAssistant: " + anItem.getItem().toString());
|
||||
if(!validHass) {
|
||||
@@ -151,6 +160,11 @@ public class HassHome implements Home {
|
||||
public void closeHome() {
|
||||
if(!validHass)
|
||||
return;
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
if(hassMap == null)
|
||||
return;
|
||||
Iterator<String> keys = hassMap.keySet().iterator();
|
||||
@@ -160,5 +174,6 @@ public class HassHome implements Home {
|
||||
}
|
||||
|
||||
hassMap = null;
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory;
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.NameValue;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHome;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class HomeAssistant {
|
||||
@@ -21,7 +22,7 @@ public class HomeAssistant {
|
||||
|
||||
public HomeAssistant(NamedIP addressName) {
|
||||
super();
|
||||
anHttpHandler = new HTTPHandler();
|
||||
anHttpHandler = HTTPHome.getHandler();
|
||||
hassAddress = addressName;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
package com.bwssystems.HABridge.plugins.homewizard;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.BridgeSettings;
|
||||
import com.bwssystems.HABridge.DeviceMapTypes;
|
||||
import com.bwssystems.HABridge.Home;
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
|
||||
/**
|
||||
* Control HomeWizard devices over HomeWizard Cloud
|
||||
*
|
||||
* @author Björn Rennfanz (bjoern@fam-rennfanz.de)
|
||||
*
|
||||
*/
|
||||
public class HomeWizardHome implements Home {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(HomeWizardHome.class);
|
||||
|
||||
private Map<String, HomeWizzardSmartPlugInfo> plugGateways;
|
||||
private Boolean validHomeWizard;
|
||||
private boolean closed;
|
||||
|
||||
public HomeWizardHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri, Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
|
||||
String responseString = null;
|
||||
if (!validHomeWizard) {
|
||||
|
||||
log.warn("Should not get here, no HomeWizard smart plug available");
|
||||
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||
+ "\",\"description\": \"Should not get here, no HomeWizard smart plug available\", \"parameter\": \"/lights/"
|
||||
+ lightId + "state\"}}]";
|
||||
} else {
|
||||
|
||||
if (anItem.getType() != null && anItem.getType().trim().equalsIgnoreCase(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex])) {
|
||||
|
||||
log.debug("Executing HUE api request to change activity to HomeWizard smart plug: " + anItem.getItem().toString());
|
||||
String jsonToPost = anItem.getItem().toString();
|
||||
|
||||
HomeWizzardSmartPlugInfo homeWizzardHandler = getHomeWizzardHandler(device.getTargetDevice());
|
||||
if(homeWizzardHandler == null) {
|
||||
log.warn("Should not get here, no HomeWizard smart plug configured");
|
||||
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||
+ "\",\"description\": \"Should not get here, no HomeWizard smart plug configured\", \"parameter\": \"/lights/"
|
||||
+ lightId + "state\"}}]";
|
||||
} else {
|
||||
try {
|
||||
homeWizzardHandler.execApply(jsonToPost);
|
||||
} catch (Exception e) {
|
||||
|
||||
log.warn("Error posting request to HomeWizard smart plug");
|
||||
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||
+ "\",\"description\": \"Error posting request to HomeWizard smart plug\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return responseString;
|
||||
}
|
||||
|
||||
public HomeWizzardSmartPlugInfo getHomeWizzardHandler(String plugName) {
|
||||
return plugGateways.get(plugName);
|
||||
}
|
||||
|
||||
public List<HomeWizardSmartPlugDevice> getDevices() {
|
||||
|
||||
log.debug("consolidating devices for HomeWizard plug gateways");
|
||||
Iterator<String> keys = plugGateways.keySet().iterator();
|
||||
ArrayList<HomeWizardSmartPlugDevice> deviceList = new ArrayList<>();
|
||||
|
||||
while(keys.hasNext())
|
||||
{
|
||||
String key = keys.next();
|
||||
for(HomeWizardSmartPlugDevice device : plugGateways.get(key).getDevices())
|
||||
deviceList.add(device);
|
||||
}
|
||||
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItems(String type) {
|
||||
|
||||
if (validHomeWizard)
|
||||
{
|
||||
if (type.equalsIgnoreCase(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex]))
|
||||
{
|
||||
return getDevices();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Home createHome(BridgeSettings bridgeSettings) {
|
||||
|
||||
validHomeWizard = bridgeSettings.getBridgeSettingsDescriptor().isValidHomeWizard();
|
||||
log.info("HomeWizard Home created. " + (validHomeWizard ? "" : "No HomeWizard gateways configured."));
|
||||
|
||||
if (validHomeWizard)
|
||||
{
|
||||
plugGateways = new HashMap<>();
|
||||
Iterator<NamedIP> gatewaysList = bridgeSettings.getBridgeSettingsDescriptor().getHomeWizardAddress().getDevices().iterator();
|
||||
|
||||
while(gatewaysList.hasNext()) {
|
||||
|
||||
NamedIP gateway = gatewaysList.next();
|
||||
plugGateways.put(gateway.getName(), new HomeWizzardSmartPlugInfo(gateway, gateway.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
|
||||
plugGateways = null;
|
||||
closed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.bwssystems.HABridge.plugins.homewizard;
|
||||
|
||||
/**
|
||||
* Control HomeWizard devices over HomeWizard Cloud
|
||||
*
|
||||
* @author Björn Rennfanz (bjoern@fam-rennfanz.de)
|
||||
*
|
||||
*/
|
||||
public class HomeWizardSmartPlugDevice {
|
||||
|
||||
private String name;
|
||||
private String gateway;
|
||||
private String id;
|
||||
private String typeName;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getGateway() {
|
||||
return gateway;
|
||||
}
|
||||
|
||||
public void setGateway(String gateway) {
|
||||
this.gateway = gateway;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTypeName() {
|
||||
return this.typeName;
|
||||
}
|
||||
|
||||
public void setTypeName(String typeName) {
|
||||
this.typeName = typeName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
package com.bwssystems.HABridge.plugins.homewizard;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.plugins.homewizard.json.Device;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* Control HomeWizard devices over HomeWizard Cloud
|
||||
*
|
||||
* @author Björn Rennfanz (bjoern@fam-rennfanz.de)
|
||||
*
|
||||
*/
|
||||
public class HomeWizzardSmartPlugInfo {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(HomeWizardHome.class);
|
||||
|
||||
private static final String HOMEWIZARD_LOGIN_URL = "https://cloud.homewizard.com/account/login";
|
||||
private static final String HOMEWIZARD_API_URL = "https://plug.homewizard.com/plugs";
|
||||
private static final String EMPTY_STRING = "";
|
||||
|
||||
private final String cloudAuth;
|
||||
private final Gson gson;
|
||||
|
||||
private String cloudSessionId;
|
||||
private String cloudPlugName;
|
||||
private String cloudPlugId;
|
||||
|
||||
public HomeWizzardSmartPlugInfo(NamedIP gateway, String name) {
|
||||
|
||||
super();
|
||||
|
||||
cloudAuth = "Basic " + new String(Base64.encodeBase64((gateway.getUsername() + ":" + DigestUtils.sha1Hex(gateway.getPassword())).getBytes()));
|
||||
cloudPlugName = name;
|
||||
gson = new Gson();
|
||||
}
|
||||
|
||||
public boolean login()
|
||||
{
|
||||
try
|
||||
{
|
||||
URL url = new URL(HOMEWIZARD_LOGIN_URL);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setRequestProperty("Authorization", cloudAuth);
|
||||
connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
|
||||
connection.connect();
|
||||
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
String line;
|
||||
|
||||
while((line = br.readLine()) != null)
|
||||
{
|
||||
buffer.append(line).append("\n");
|
||||
}
|
||||
br.close();
|
||||
|
||||
// Get session id from result JSON
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject json = parser.parse(buffer.toString()).getAsJsonObject();
|
||||
|
||||
cloudSessionId = json.get("session").getAsString();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
log.warn("Error while login to cloud service ", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private String requestJson(String request)
|
||||
{
|
||||
String result = null;
|
||||
|
||||
// Check login was successful
|
||||
if (login()) {
|
||||
|
||||
// Request JSON from Cloud service
|
||||
try
|
||||
{
|
||||
URL url = new URL(HOMEWIZARD_API_URL + request);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setRequestProperty("X-Session-Token", cloudSessionId);
|
||||
connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
|
||||
connection.connect();
|
||||
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
String line;
|
||||
|
||||
while((line = br.readLine()) != null)
|
||||
{
|
||||
buffer.append(line).append("\n");
|
||||
}
|
||||
|
||||
br.close();
|
||||
|
||||
result = buffer.toString();
|
||||
result = StringUtils.strip(result, "[]");
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
log.warn("Error while get json request: {} ", request, e);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean sendAction(String request, String action)
|
||||
{
|
||||
boolean result = true;
|
||||
|
||||
// Check login was successful
|
||||
if (login()) {
|
||||
|
||||
// Post action into Cloud service
|
||||
try
|
||||
{
|
||||
URL url = new URL(HOMEWIZARD_API_URL + request);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
JsonObject actionJson = new JsonObject();
|
||||
actionJson.addProperty("action", StringUtils.capitalize(action));
|
||||
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setDoOutput(true);
|
||||
connection.setRequestProperty("X-Session-Token", cloudSessionId);
|
||||
connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
|
||||
|
||||
OutputStream os = connection.getOutputStream();
|
||||
os.write(actionJson.toString().getBytes("UTF-8"));
|
||||
os.close();
|
||||
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
String line;
|
||||
|
||||
while((line = br.readLine()) != null)
|
||||
{
|
||||
buffer.append(line).append("\n");
|
||||
}
|
||||
|
||||
br.close();
|
||||
connection.disconnect();
|
||||
|
||||
// Check if request was Ok
|
||||
if (!buffer.toString().contains("Success"))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
log.warn("Error while post json action: {} ", request, e);
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<HomeWizardSmartPlugDevice> getDevices()
|
||||
{
|
||||
List<HomeWizardSmartPlugDevice> homewizardDevices = new ArrayList<>();
|
||||
try {
|
||||
|
||||
String result = requestJson(EMPTY_STRING);
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject resultJson = parser.parse(result).getAsJsonObject();
|
||||
cloudPlugId = resultJson.get("id").getAsString();
|
||||
|
||||
String all_devices_json = resultJson.get("devices").toString();
|
||||
Device[] devices = gson.fromJson(all_devices_json, Device[].class);
|
||||
|
||||
// Fix names from JSON
|
||||
for (Device device : devices) {
|
||||
device.setTypeName(StringUtils.capitalize(device.getTypeName().replace("_", " ")));
|
||||
homewizardDevices.add(mapDeviceToHomeWizardSmartPlugDevice(device));
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
log.warn("Error while get devices from cloud service ", e);
|
||||
}
|
||||
|
||||
log.info("Found: " + homewizardDevices.size() + " devices");
|
||||
return homewizardDevices;
|
||||
}
|
||||
|
||||
public void execApply(String jsonToPost) throws Exception {
|
||||
|
||||
// Extract
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject resultJson = parser.parse(jsonToPost).getAsJsonObject();
|
||||
String deviceId = resultJson.get("deviceid").getAsString();
|
||||
String action = resultJson.get("action").getAsString();
|
||||
|
||||
// Check if we have an plug id stored
|
||||
if (StringUtils.isBlank(cloudPlugId)) {
|
||||
getDevices();
|
||||
}
|
||||
|
||||
// Send request to HomeWizard cloud
|
||||
if (!sendAction("/" + cloudPlugId + "/devices/" + deviceId + "/action", action))
|
||||
{
|
||||
throw new IOException("Send action to HomeWizard Cloud failed.");
|
||||
}
|
||||
}
|
||||
|
||||
protected HomeWizardSmartPlugDevice mapDeviceToHomeWizardSmartPlugDevice(Device device) {
|
||||
HomeWizardSmartPlugDevice homewizardDevice = new HomeWizardSmartPlugDevice();
|
||||
homewizardDevice.setId(device.getId());
|
||||
homewizardDevice.setGateway(cloudPlugName);
|
||||
homewizardDevice.setName(device.getName());
|
||||
homewizardDevice.setTypeName(device.getTypeName());
|
||||
|
||||
return homewizardDevice;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.bwssystems.HABridge.plugins.homewizard.json;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Control HomeWizard devices over HomeWizard Cloud
|
||||
*
|
||||
* @author Björn Rennfanz (bjoern@fam-rennfanz.de)
|
||||
*
|
||||
*/
|
||||
public class Device {
|
||||
|
||||
@SerializedName("id")
|
||||
@Expose
|
||||
private String id;
|
||||
|
||||
@SerializedName("name")
|
||||
@Expose
|
||||
private String name;
|
||||
|
||||
@SerializedName("typeName")
|
||||
@Expose
|
||||
private String typeName;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getTypeName() {
|
||||
return this.typeName;
|
||||
}
|
||||
|
||||
public void setTypeName(String typeName) {
|
||||
this.typeName = typeName;
|
||||
}
|
||||
}
|
||||
@@ -5,44 +5,50 @@ import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.config.CookieSpecs;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
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.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.DeviceMapTypes;
|
||||
import com.bwssystems.HABridge.api.NameValue;
|
||||
|
||||
public class HTTPHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger(HTTPHandler.class);
|
||||
private CloseableHttpClient httpClient;
|
||||
private RequestConfig globalConfig;
|
||||
|
||||
private String callType;
|
||||
|
||||
public HTTPHandler() {
|
||||
globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();
|
||||
httpClient = HttpClients.custom().setDefaultRequestConfig(globalConfig).build();
|
||||
super();
|
||||
callType = null;
|
||||
}
|
||||
|
||||
|
||||
public HTTPHandler(String type) {
|
||||
super();
|
||||
callType = type;
|
||||
}
|
||||
|
||||
|
||||
// This function executes the url from the device repository against the
|
||||
// target as http or https as defined
|
||||
public String doHttpRequest(String url, String httpVerb, String contentType, String body, NameValue[] headers) {
|
||||
log.debug("doHttpRequest with url: " + url + " with http command: " + httpVerb + " with body: " + body);
|
||||
log.debug("doHttpRequest with url <<<" + url + ">>>, verb: " + httpVerb + ", contentType: " + contentType + ", body <<<" + body + ">>>" );
|
||||
if(headers != null && headers.length > 0)
|
||||
for(int i = 0; i < headers.length; i++)
|
||||
log.debug("header index " + i + " name: <<<" + headers[i].getName() + ">>>, value: <<<" + headers[i].getValue() + ">>>");
|
||||
HttpUriRequest request = null;
|
||||
String theContent = null;
|
||||
URI theURI = null;
|
||||
ContentType parsedContentType = null;
|
||||
StringEntity requestBody = null;
|
||||
|
||||
if (contentType != null && !contentType.trim().isEmpty()) {
|
||||
parsedContentType = ContentType.parse(contentType);
|
||||
if (body != null && body.length() > 0)
|
||||
@@ -54,6 +60,7 @@ public class HTTPHandler {
|
||||
log.warn("Error creating URI http request: " + url + " with message: " + e1.getMessage());
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (httpVerb == null || httpVerb.trim().isEmpty() || HttpGet.METHOD_NAME.equalsIgnoreCase(httpVerb)) {
|
||||
request = new HttpGet(theURI);
|
||||
@@ -67,93 +74,86 @@ public class HTTPHandler {
|
||||
if (requestBody != null)
|
||||
putRequest.setEntity(requestBody);
|
||||
request = putRequest;
|
||||
}
|
||||
else
|
||||
} else
|
||||
request = new HttpGet(theURI);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.warn("Error creating outbound http request: IllegalArgumentException in log", e);
|
||||
return null;
|
||||
}
|
||||
log.debug("Making outbound call in doHttpRequest: " + request);
|
||||
log.debug("Making outbound call in doHttpRequest: <<<" + request.toString() + ">>>");
|
||||
if (headers != null && headers.length > 0) {
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
request.setHeader(headers[i].getName(), headers[i].getValue());
|
||||
}
|
||||
}
|
||||
HttpResponse response;
|
||||
try {
|
||||
for(int retryCount = 0; retryCount < 2; retryCount++) {
|
||||
response = httpClient.execute(request);
|
||||
CloseableHttpResponse response = null;
|
||||
for (int retryCount = 0; retryCount < 2; retryCount++) {
|
||||
try {
|
||||
response = HttpClientPool.getClient().execute(request);
|
||||
log.debug((httpVerb == null ? "GET" : httpVerb) + " execute (" + retryCount + ") on URL responded: "
|
||||
+ response.getStatusLine().getStatusCode());
|
||||
if (response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300) {
|
||||
if (response.getEntity() != null) {
|
||||
try {
|
||||
theContent = EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8")); // read
|
||||
// content
|
||||
// for
|
||||
// data
|
||||
EntityUtils.consume(response.getEntity()); // close out
|
||||
// inputstream
|
||||
// ignore
|
||||
// content
|
||||
} catch (Exception e) {
|
||||
log.debug("Error ocurred in handling response entity after successful call, still responding success. "
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
log.debug("Successfull response - The http response is <<<" + theContent + ">>>");
|
||||
}
|
||||
retryCount = 2;
|
||||
} else {
|
||||
log.warn("HTTP response code was not an expected successful response of between 200 - 299, the code was: " + response.getStatusLine());
|
||||
if (response != null && response.getEntity() != null) {
|
||||
try {
|
||||
String someContent = EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8")); // read
|
||||
// content
|
||||
// for
|
||||
// data
|
||||
|
||||
theContent = EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8")); // read
|
||||
// content
|
||||
// for
|
||||
// data
|
||||
|
||||
EntityUtils.consume(response.getEntity()); // close out
|
||||
// inputstream
|
||||
// ignore
|
||||
// content
|
||||
log.debug("Unsuccessfull response - The http response is <<<" + someContent + ">>>");
|
||||
// inputstream
|
||||
// ignore
|
||||
// content
|
||||
} catch (Exception e) {
|
||||
//noop
|
||||
log.debug("Error ocurred in handling response entity after successful call, still responding success. "
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
if (response != null && response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300) {
|
||||
if(theContent == null)
|
||||
theContent = "";
|
||||
log.debug("Successfull response - The http response is <<<" + theContent + ">>>");
|
||||
retryCount = 2;
|
||||
} else if (callType != null && callType == DeviceMapTypes.FHEM_DEVICE[DeviceMapTypes.typeIndex] && response.getStatusLine().getStatusCode() == 302) {
|
||||
if(theContent == null)
|
||||
theContent = "";
|
||||
log.debug("Successfull response - The http response is <<<" + theContent + ">>>");
|
||||
retryCount = 2;
|
||||
} else if (response != null) {
|
||||
log.warn("HTTP response code was not an expected successful response of between 200 - 299, the code was: "
|
||||
+ response.getStatusLine() + " with the content of <<<" + theContent + ">>>");
|
||||
if (response.getStatusLine().getStatusCode() == 504) {
|
||||
log.warn("HTTP response code was 504, retrying...");
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e1) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
else
|
||||
log.debug("The 504 error content is <<<" + theContent + ">>>");
|
||||
theContent = null;
|
||||
} else
|
||||
retryCount = 2;
|
||||
}
|
||||
|
||||
} catch (ClientProtocolException e) {
|
||||
log.warn("Client Protocol Exception received, retyring....");
|
||||
}catch (IOException e) {
|
||||
log.warn("Error calling out to HA gateway: IOException in log: " + e.getMessage());
|
||||
retryCount = 2;
|
||||
}
|
||||
|
||||
if(retryCount < 2) {
|
||||
theContent = null;
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e1) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.warn("Error calling out to HA gateway: IOException in log", e);
|
||||
}
|
||||
return theContent;
|
||||
}
|
||||
|
||||
// public HttpClient getHttpClient() {
|
||||
// return httpClient;
|
||||
// }
|
||||
|
||||
|
||||
public CloseableHttpClient getHttpClient() {
|
||||
return httpClient;
|
||||
public void setCallType(String callType) {
|
||||
this.callType = callType;
|
||||
}
|
||||
|
||||
|
||||
public void closeHandler() {
|
||||
try {
|
||||
httpClient.close();
|
||||
} catch (IOException e) {
|
||||
// noop
|
||||
}
|
||||
httpClient = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,23 +11,37 @@ import com.bwssystems.HABridge.api.hue.HueError;
|
||||
import com.bwssystems.HABridge.api.hue.HueErrorResponse;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.ColorDecode;
|
||||
import com.bwssystems.HABridge.hue.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
import com.bwssystems.HABridge.plugins.fibaro.FibaroTestData;
|
||||
import com.bwssystems.HABridge.plugins.vera.VeraTestData;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class HTTPHome implements Home {
|
||||
private static final Logger log = LoggerFactory.getLogger(HTTPHome.class);
|
||||
private HTTPHandler anHttpHandler;
|
||||
private static HTTPHandler anHttpHandler = null;
|
||||
private Boolean isDevMode;
|
||||
private boolean closed;
|
||||
|
||||
public HTTPHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
public static HTTPHandler getHandler() {
|
||||
if(anHttpHandler == null)
|
||||
anHttpHandler = new HTTPHandler();
|
||||
return anHttpHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
String responseString = null;
|
||||
|
||||
String theUrl = anItem.getItem().getAsString();
|
||||
@@ -50,6 +64,9 @@ public class HTTPHome implements Home {
|
||||
|
||||
String anUrl = BrightnessDecode.calculateReplaceIntensityValue(theUrl,
|
||||
intensity, targetBri, targetBriInc, false);
|
||||
if (colorData != null) {
|
||||
anUrl = ColorDecode.replaceColorData(anUrl, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false);
|
||||
}
|
||||
anUrl = DeviceDataDecode.replaceDeviceData(anUrl, device);
|
||||
anUrl = TimeDecode.replaceTimeValue(anUrl);
|
||||
|
||||
@@ -57,17 +74,23 @@ public class HTTPHome implements Home {
|
||||
if(anItem.getHttpBody()!= null && !anItem.getHttpBody().isEmpty()) {
|
||||
aBody = BrightnessDecode.calculateReplaceIntensityValue(anItem.getHttpBody(),
|
||||
intensity, targetBri, targetBriInc, false);
|
||||
if (colorData != null) {
|
||||
aBody = ColorDecode.replaceColorData(aBody, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false);
|
||||
}
|
||||
aBody = DeviceDataDecode.replaceDeviceData(aBody, device);
|
||||
aBody = TimeDecode.replaceTimeValue(aBody);
|
||||
}
|
||||
// make call
|
||||
if (anHttpHandler.doHttpRequest(anUrl, anItem.getHttpVerb(), anItem.getContentType(), aBody,
|
||||
new Gson().fromJson(anItem.getHttpHeaders(), NameValue[].class)) == null) {
|
||||
String httpReply = anHttpHandler.doHttpRequest(anUrl, anItem.getHttpVerb(), anItem.getContentType(), aBody, new Gson().fromJson(anItem.getHttpHeaders(), NameValue[].class));
|
||||
if (httpReply == null) {
|
||||
log.warn("Error on calling url to change device state: " + anUrl);
|
||||
responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId,
|
||||
"Error on calling url to change device state", "/lights/"
|
||||
+ lightId + "state", null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
|
||||
if(isDevMode)
|
||||
log.info("Dev Mode response dump <<<" + httpReply +">>>");
|
||||
} else {
|
||||
log.warn("HTTP Call to be presented as http(s)://<ip_address>(:<port>)/payload, format of request unknown: " + theUrl);
|
||||
responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId,
|
||||
@@ -80,8 +103,21 @@ public class HTTPHome implements Home {
|
||||
|
||||
@Override
|
||||
public Home createHome(BridgeSettings bridgeSettings) {
|
||||
anHttpHandler = new HTTPHandler();
|
||||
log.info("Http Home created.");
|
||||
isDevMode = Boolean.parseBoolean(System.getProperty("dev.mode", "false"));
|
||||
log.info("HTTP Home created." + (isDevMode ? " DevMode is set." : ""));
|
||||
if(isDevMode) {
|
||||
anHttpHandler = new HttpTestHandler();
|
||||
((HttpTestHandler)anHttpHandler).setTheData("id=sdata", VeraTestData.SDataTestData);
|
||||
((HttpTestHandler)anHttpHandler).setTheData("action=SetLoadLevelTarget", VeraTestData.SetLoadLevelTargetData);
|
||||
((HttpTestHandler)anHttpHandler).setTheData("action=SetTarget", VeraTestData.SetTargetData);
|
||||
((HttpTestHandler)anHttpHandler).setTheData("action=RunScene", VeraTestData.RunSceneData);
|
||||
((HttpTestHandler)anHttpHandler).setTheData("/api/callAction", FibaroTestData.CallActionTestData);
|
||||
((HttpTestHandler)anHttpHandler).setTheData("/api/sceneControl", FibaroTestData.SceneControlTestData);
|
||||
((HttpTestHandler)anHttpHandler).setTheData(null, "generic treply - no match");
|
||||
|
||||
}
|
||||
if(anHttpHandler == null)
|
||||
anHttpHandler = new HTTPHandler();
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -93,9 +129,19 @@ public class HTTPHome implements Home {
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
if(anHttpHandler != null)
|
||||
anHttpHandler.closeHandler();
|
||||
anHttpHandler = null;
|
||||
closed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
// noop
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.bwssystems.HABridge.plugins.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public final class HttpClientPool {
|
||||
private static final Logger log = LoggerFactory.getLogger(HttpClientPool.class);
|
||||
|
||||
// Single-element enum to implement Singleton.
|
||||
private static enum Singleton {
|
||||
// Just one of me so constructor will be called once.
|
||||
Client;
|
||||
// The thread-safe client.
|
||||
private final CloseableHttpClient threadSafeClient;
|
||||
// The pool monitor.
|
||||
private final IdleConnectionMonitorThread monitor;
|
||||
|
||||
// The constructor creates it - thus late
|
||||
private Singleton() {
|
||||
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
|
||||
// Increase max total connection to 200
|
||||
cm.setMaxTotal(200);
|
||||
// Increase default max connection per route to 20
|
||||
cm.setDefaultMaxPerRoute(20);
|
||||
// Build the client.
|
||||
threadSafeClient = HttpClients.custom()
|
||||
.setConnectionManager(cm)
|
||||
.build();
|
||||
// Start up an eviction thread.
|
||||
monitor = new IdleConnectionMonitorThread(cm);
|
||||
// Don't stop quitting.
|
||||
monitor.setDaemon(true);
|
||||
monitor.start();
|
||||
}
|
||||
|
||||
public CloseableHttpClient get() {
|
||||
return threadSafeClient;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static CloseableHttpClient getClient() {
|
||||
// The thread safe client is held by the singleton.
|
||||
return Singleton.Client.get();
|
||||
}
|
||||
|
||||
// Watches for stale connections and evicts them.
|
||||
private static class IdleConnectionMonitorThread extends Thread {
|
||||
// The manager to watch.
|
||||
private final PoolingHttpClientConnectionManager cm;
|
||||
// Use a BlockingQueue to stop everything.
|
||||
private final BlockingQueue<Stop> stopSignal = new ArrayBlockingQueue<Stop>(1);
|
||||
|
||||
// Pushed up the queue.
|
||||
private static class Stop {
|
||||
// The return queue.
|
||||
private final BlockingQueue<Stop> stop = new ArrayBlockingQueue<Stop>(1);
|
||||
|
||||
// Called by the process that is being told to stop.
|
||||
public void stopped() {
|
||||
// Push me back up the queue to indicate we are now stopped.
|
||||
stop.add(this);
|
||||
}
|
||||
|
||||
// Called by the process requesting the stop.
|
||||
public void waitForStopped() throws InterruptedException {
|
||||
// Wait until the callee acknowledges that it has stopped.
|
||||
stop.take();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
IdleConnectionMonitorThread(PoolingHttpClientConnectionManager cm) {
|
||||
super();
|
||||
this.cm = cm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// Holds the stop request that stopped the process.
|
||||
Stop stopRequest;
|
||||
// Every 5 seconds.
|
||||
while ((stopRequest = stopSignal.poll(5, TimeUnit.SECONDS)) == null) {
|
||||
// Close expired connections
|
||||
cm.closeExpiredConnections();
|
||||
// Optionally, close connections that have been idle too long.
|
||||
cm.closeIdleConnections(60, TimeUnit.SECONDS);
|
||||
// Look at pool stats.
|
||||
log.debug("Stats: {}", cm.getTotalStats());
|
||||
}
|
||||
// Acknowledge the stop request.
|
||||
stopRequest.stopped();
|
||||
} catch (InterruptedException ex) {
|
||||
// terminate
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() throws InterruptedException, IOException {
|
||||
log.info("Shutting down client pool");
|
||||
// Signal the stop to the thread.
|
||||
Stop stop = new Stop();
|
||||
stopSignal.add(stop);
|
||||
// Wait for the stop to complete.
|
||||
stop.waitForStopped();
|
||||
// Close the pool - Added
|
||||
Singleton.Client.threadSafeClient.close();
|
||||
// Close the connection manager.
|
||||
cm.close();
|
||||
log.info("Client pool shut down");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void shutdown() throws InterruptedException, IOException {
|
||||
// Shutdown the monitor.
|
||||
Singleton.Client.monitor.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.bwssystems.HABridge.plugins.http;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.api.NameValue;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
|
||||
public class HttpTestHandler extends HTTPHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger(HttpTestHandler.class);
|
||||
private List<NameValue> theData;
|
||||
|
||||
public void setTheData(String compareValue, String testData) {
|
||||
if( this.theData == null )
|
||||
this.theData = new ArrayList<NameValue>();
|
||||
NameValue aValueSet = new NameValue();
|
||||
aValueSet.setName(compareValue);
|
||||
aValueSet.setValue(testData);
|
||||
this.theData.add(aValueSet);
|
||||
}
|
||||
|
||||
public void updateTheData(String compareValue, String testData) {
|
||||
if( this.theData == null ) {
|
||||
this.theData = new ArrayList<NameValue>();
|
||||
NameValue aValueSet = new NameValue();
|
||||
aValueSet.setName(compareValue);
|
||||
aValueSet.setValue(testData);
|
||||
this.theData.add(aValueSet);
|
||||
}
|
||||
else {
|
||||
for(NameValue aTest:this.theData) {
|
||||
if(aTest.getName().equals(compareValue));
|
||||
aTest.setValue(testData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String doHttpRequest(String url, String httpVerb, String contentType, String body, NameValue[] headers) {
|
||||
log.info("doHttpRequest with url <<<" + url + ">>>, verb: " + httpVerb + ", contentType: " + contentType + ", body <<<" + body + ">>>" );
|
||||
if(headers != null && headers.length > 0)
|
||||
for(int i = 0; i < headers.length; i++)
|
||||
log.info("header index " + i + " name: <<<" + headers[i].getName() + ">>>, value: <<<" + headers[i].getValue() + ">>>");
|
||||
String responseData = null;
|
||||
for(NameValue aTest:theData) {
|
||||
if(aTest.getName() == null)
|
||||
responseData = aTest.getValue();
|
||||
else {
|
||||
if(url.contains(aTest.getName()))
|
||||
responseData = aTest.getValue();
|
||||
else if(aTest.getName() == null || aTest.getName().isEmpty())
|
||||
responseData = aTest.getValue();
|
||||
}
|
||||
|
||||
if(responseData != null)
|
||||
break;
|
||||
}
|
||||
|
||||
if(responseData == null)
|
||||
responseData = "No data was set for HttpTestHandler for your request url.";
|
||||
return responseData;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -15,6 +16,7 @@ import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
||||
import com.bwssystems.HABridge.api.hue.HueApiResponse;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
@@ -24,10 +26,15 @@ public class HueHome implements Home {
|
||||
private Map<String, HueInfo> hues;
|
||||
private Boolean validHue;
|
||||
private Gson aGsonHandler;
|
||||
private BridgeSettings theBridgeSettings;
|
||||
private boolean closed;
|
||||
|
||||
public HueHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
theBridgeSettings = bridgeSettings;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,7 +91,7 @@ public class HueHome implements Home {
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
if(!validHue)
|
||||
return null;
|
||||
String responseString = null;
|
||||
@@ -113,17 +120,29 @@ public class HueHome implements Home {
|
||||
Iterator<NamedIP> theList = bridgeSettings.getBridgeSettingsDescriptor().getHueaddress().getDevices().iterator();
|
||||
while(theList.hasNext()) {
|
||||
NamedIP aHue = theList.next();
|
||||
hues.put(aHue.getName(), new HueInfo(aHue));
|
||||
hues.put(aHue.getName(), new HueInfo(aHue, this));
|
||||
}
|
||||
aGsonHandler = new GsonBuilder().create();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
protected void updateHue(NamedIP aHue) {
|
||||
theBridgeSettings.getBridgeSettingsDescriptor().updateHue(aHue);
|
||||
if(theBridgeSettings.getBridgeSettingsDescriptor().isSettingsChanged()) {
|
||||
theBridgeSettings.updateConfigFile();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
if(!validHue)
|
||||
return;
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
if(hues == null)
|
||||
return;
|
||||
Iterator<String> keys = hues.keySet().iterator();
|
||||
@@ -132,5 +151,11 @@ public class HueHome implements Home {
|
||||
hues.get(key).closeHue();;
|
||||
}
|
||||
hues = null;
|
||||
closed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
package com.bwssystems.HABridge.plugins.hue;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.HttpClient;
|
||||
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.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -20,19 +13,22 @@ import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
||||
import com.bwssystems.HABridge.api.hue.HueApiResponse;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHome;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
|
||||
public class HueInfo {
|
||||
private static final Logger log = LoggerFactory.getLogger(HueInfo.class);
|
||||
private HTTPHandler httpClient;
|
||||
private HTTPHandler httpHandler;
|
||||
private NamedIP hueAddress;
|
||||
private HueHome myHome;
|
||||
public static final String HUE_REQUEST = "/api";
|
||||
|
||||
public HueInfo(NamedIP addressName) {
|
||||
public HueInfo(NamedIP addressName, HueHome theHome) {
|
||||
super();
|
||||
httpClient = new HTTPHandler();
|
||||
httpHandler = HTTPHome.getHandler();
|
||||
hueAddress = addressName;
|
||||
myHome = theHome;
|
||||
}
|
||||
|
||||
public HueApiResponse getHueApiResponse() {
|
||||
@@ -62,8 +58,8 @@ public class HueInfo {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
theUrl = "http://" + hueAddress.getIp() + HueUtil.HUE_REQUEST + "/" + hueAddress.getUsername();
|
||||
theData = httpClient.doHttpRequest(theUrl, null, null, null, null);
|
||||
theUrl = "http://" + hueAddress.getIp() + HUE_REQUEST + "/" + hueAddress.getUsername();
|
||||
theData = httpHandler.doHttpRequest(theUrl, null, null, null, null);
|
||||
if(theData != null) {
|
||||
log.debug("GET HueApiResponse - data: " + theData);
|
||||
if(theData.contains("[{\"error\":")) {
|
||||
@@ -96,34 +92,25 @@ public class HueInfo {
|
||||
public String registerWithHue() {
|
||||
UserCreateRequest theLogin = new UserCreateRequest();
|
||||
theLogin.setDevicetype("HABridge#MyMachine");
|
||||
HttpPost postRequest = new HttpPost("http://" + hueAddress.getIp() + HUE_REQUEST);
|
||||
ContentType parsedContentType = ContentType.parse("application/json");
|
||||
StringEntity requestBody = new StringEntity(new Gson().toJson(theLogin), parsedContentType);
|
||||
HttpResponse response = null;
|
||||
postRequest.setEntity(requestBody);
|
||||
HttpClient anHttpClient = httpClient.getHttpClient();
|
||||
try {
|
||||
response = anHttpClient.execute(postRequest);
|
||||
log.debug("registerWithHue - POST execute on " + hueAddress.getName() + "URL responded: " + response.getStatusLine().getStatusCode());
|
||||
if(response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300){
|
||||
String theBody = EntityUtils.toString(response.getEntity());
|
||||
log.debug("registerWithHue response data: " + theBody);
|
||||
if(theBody.contains("[{\"error\":")) {
|
||||
if(theBody.contains("link button not")) {
|
||||
|
||||
String aMessage = httpHandler.doHttpRequest("http://" + hueAddress.getIp() + HUE_REQUEST, HttpPost.METHOD_NAME, "application/json", new Gson().toJson(theLogin), null);
|
||||
|
||||
log.debug("registerWithHue - POST execute on " + hueAddress.getName() + "URL responded: " + aMessage);
|
||||
if(!aMessage.isEmpty()){
|
||||
log.debug("registerWithHue response data: " + aMessage);
|
||||
if(aMessage.contains("[{\"error\":")) {
|
||||
if(aMessage.contains("link button not")) {
|
||||
log.warn("registerWithHue needs link button pressed on HUE bridge: " + hueAddress.getName());
|
||||
}
|
||||
else
|
||||
log.warn("registerWithHue returned an unexpected error: " + theBody);
|
||||
log.warn("registerWithHue returned an unexpected error: " + aMessage);
|
||||
}
|
||||
else {
|
||||
SuccessUserResponse[] theResponses = new Gson().fromJson(theBody, SuccessUserResponse[].class); //read content for data, SuccessUserResponse[].class);
|
||||
SuccessUserResponse[] theResponses = new Gson().fromJson(aMessage, SuccessUserResponse[].class); //read content for data, SuccessUserResponse[].class);
|
||||
hueAddress.setUsername(theResponses[0].getSuccess().getUsername());
|
||||
myHome.updateHue(hueAddress);
|
||||
}
|
||||
}
|
||||
EntityUtils.consume(response.getEntity()); //close out inputstream ignore content
|
||||
} catch (IOException e) {
|
||||
log.warn("Error logging into HUE: IOException in log", e);
|
||||
}
|
||||
return hueAddress.getUsername();
|
||||
}
|
||||
|
||||
@@ -135,7 +122,7 @@ public class HueInfo {
|
||||
registerWithHue();
|
||||
if (hueAddress.getUsername() != null) {
|
||||
// make call
|
||||
responseString = httpClient.doHttpRequest(
|
||||
responseString = httpHandler.doHttpRequest(
|
||||
"http://" + hueAddress.getIp() + "/api/" + hueAddress.getUsername()
|
||||
+ "/lights/" + hueDeviceId,
|
||||
HttpGet.METHOD_NAME, "application/json", null, null);
|
||||
@@ -164,7 +151,7 @@ public class HueInfo {
|
||||
if(hueAddress.getUsername() == null)
|
||||
registerWithHue();
|
||||
if (hueAddress.getUsername() != null) {
|
||||
responseString = httpClient.doHttpRequest(
|
||||
responseString = httpHandler.doHttpRequest(
|
||||
"http://" + deviceId.getIpAddress() + "/api/" + hueAddress.getUsername()
|
||||
+ "/lights/" + deviceId.getDeviceId() + "/state",
|
||||
HttpPut.METHOD_NAME, "application/json", body, null);
|
||||
@@ -185,8 +172,8 @@ public class HueInfo {
|
||||
}
|
||||
|
||||
public void closeHue() {
|
||||
httpClient.closeHandler();
|
||||
httpClient = null;
|
||||
httpHandler.closeHandler();
|
||||
httpHandler = null;
|
||||
}
|
||||
|
||||
public NamedIP getHueAddress() {
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
package com.bwssystems.HABridge.plugins.hue;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.api.SuccessUserResponse;
|
||||
import com.bwssystems.HABridge.api.UserCreateRequest;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class HueUtil {
|
||||
private static final Logger log = LoggerFactory.getLogger(HueUtil.class);
|
||||
public static final String HUE_REQUEST = "/api";
|
||||
|
||||
public static final String registerWithHue(HTTPHandler anHttpHandler, String ipAddress, String aName, String theUser) {
|
||||
UserCreateRequest theLogin = new UserCreateRequest();
|
||||
theLogin.setDevicetype("HABridge#MyMachine");
|
||||
HttpPost postRequest = new HttpPost("http://" + ipAddress + HUE_REQUEST);
|
||||
ContentType parsedContentType = ContentType.parse("application/json");
|
||||
StringEntity requestBody = new StringEntity(new Gson().toJson(theLogin), parsedContentType);
|
||||
HttpResponse response = null;
|
||||
postRequest.setEntity(requestBody);
|
||||
HttpClient anHttpClient = anHttpHandler.getHttpClient();
|
||||
try {
|
||||
response = anHttpClient.execute(postRequest);
|
||||
log.debug("POST execute on URL responded: " + response.getStatusLine().getStatusCode());
|
||||
if(response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300){
|
||||
String theBody = EntityUtils.toString(response.getEntity());
|
||||
log.debug("registerWithHue response data: " + theBody);
|
||||
if(theBody.contains("[{\"error\":")) {
|
||||
if(theBody.contains("link button not")) {
|
||||
log.warn("registerWithHue needs link button pressed on HUE bridge: " + aName);
|
||||
}
|
||||
else
|
||||
log.warn("registerWithHue returned an unexpected error: " + theBody);
|
||||
}
|
||||
else {
|
||||
SuccessUserResponse[] theResponses = new Gson().fromJson(theBody, SuccessUserResponse[].class); //read content for data, SuccessUserResponse[].class);
|
||||
theUser = theResponses[0].getSuccess().getUsername();
|
||||
}
|
||||
}
|
||||
EntityUtils.consume(response.getEntity()); //close out inputstream ignore content
|
||||
} catch (IOException e) {
|
||||
log.warn("Error logging into HUE: IOException in log", e);
|
||||
}
|
||||
return theUser;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InterfaceAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
@@ -19,6 +20,8 @@ import com.bwssystems.HABridge.Home;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.ColorDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.github.besherman.lifx.LFXClient;
|
||||
import com.github.besherman.lifx.LFXGroup;
|
||||
@@ -37,10 +40,14 @@ public class LifxHome implements Home {
|
||||
private LFXClient client;
|
||||
private Boolean validLifx;
|
||||
private Gson aGsonHandler;
|
||||
private InetAddress configuredAddress;
|
||||
private boolean closed;
|
||||
|
||||
public LifxHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -50,47 +57,17 @@ public class LifxHome implements Home {
|
||||
validLifx = bridgeSettings.getBridgeSettingsDescriptor().isValidLifx();
|
||||
log.info("LifxDevice Home created." + (validLifx ? "" : " No LifxDevices configured."));
|
||||
if(validLifx) {
|
||||
try {
|
||||
log.info("Open Lifx client....");
|
||||
InetAddress configuredAddress = InetAddress.getByName(bridgeSettings.getBridgeSettingsDescriptor().getUpnpConfigAddress());
|
||||
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(configuredAddress);
|
||||
InetAddress bcastInetAddr = null;
|
||||
if (networkInterface != null) {
|
||||
for (InterfaceAddress ifaceAddr : networkInterface.getInterfaceAddresses()) {
|
||||
InetAddress addr = ifaceAddr.getAddress();
|
||||
if (addr instanceof Inet4Address) {
|
||||
bcastInetAddr = ifaceAddr.getBroadcast();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bcastInetAddr != null) {
|
||||
lifxMap = new HashMap<String, LifxDevice>();
|
||||
log.info("Opening LFX Client with broadcast address: " + bcastInetAddr.getHostAddress());
|
||||
client = new LFXClient(bcastInetAddr.getHostAddress());
|
||||
client.getLights().addLightCollectionListener(new MyLightListener(lifxMap));
|
||||
client.getGroups().addGroupCollectionListener(new MyGroupListener(lifxMap));
|
||||
client.open(false);
|
||||
aGsonHandler =
|
||||
new GsonBuilder()
|
||||
.create();
|
||||
} else {
|
||||
log.warn("Could not open LIFX, no bcast addr available, check your upnp config address.");
|
||||
client = null;
|
||||
validLifx = false;
|
||||
return this;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.warn("Could not open LIFX, with IO Exception", e);
|
||||
client = null;
|
||||
validLifx = false;
|
||||
return this;
|
||||
} catch (InterruptedException e) {
|
||||
log.warn("Could not open LIFX, with Interruprted Exception", e);
|
||||
client = null;
|
||||
aGsonHandler =
|
||||
new GsonBuilder()
|
||||
.create();
|
||||
try {
|
||||
configuredAddress = InetAddress.getByName(bridgeSettings.getBridgeSettingsDescriptor().getUpnpConfigAddress());
|
||||
} catch (UnknownHostException e) {
|
||||
log.warn("Could not get Inet Address for Lifx broadcast.");
|
||||
validLifx = false;
|
||||
return this;
|
||||
}
|
||||
broadcastDiscover();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -112,7 +89,7 @@ public class LifxHome implements Home {
|
||||
@Override
|
||||
public Object getItems(String type) {
|
||||
log.debug("consolidating devices for lifx");
|
||||
if(!validLifx)
|
||||
if(!validLifx || lifxMap == null)
|
||||
return null;
|
||||
LifxEntry theResponse = null;
|
||||
Iterator<String> keys = lifxMap.keySet().iterator();
|
||||
@@ -130,6 +107,7 @@ public class LifxHome implements Home {
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private Boolean addLifxLights(LFXLightCollection theDeviceList) {
|
||||
if(!validLifx)
|
||||
return false;
|
||||
@@ -142,6 +120,7 @@ public class LifxHome implements Home {
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private Boolean addLifxGroups(LFXGroupCollection theDeviceList) {
|
||||
if(!validLifx)
|
||||
return false;
|
||||
@@ -156,7 +135,7 @@ public class LifxHome implements Home {
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri, Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri, Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
String theReturn = null;
|
||||
float aBriValue;
|
||||
float theValue;
|
||||
@@ -194,6 +173,10 @@ public class LifxHome implements Home {
|
||||
theValue = (float)0.99;
|
||||
theLight.setBrightness(theValue);
|
||||
}
|
||||
if(colorData != null) {
|
||||
int rgbVal = ColorDecode.getIntRGB(colorData, intensity);
|
||||
theLight.setColor(rgbVal);
|
||||
}
|
||||
} else if (theDevice.getType().equals(LifxDevice.GROUP_TYPE)) {
|
||||
LFXGroup theGroup = (LFXGroup)theDevice.getLifxObject();
|
||||
if(body.contains("true"))
|
||||
@@ -210,7 +193,14 @@ public class LifxHome implements Home {
|
||||
public void closeHome() {
|
||||
if(!validLifx)
|
||||
return;
|
||||
client.close();
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
if(client != null)
|
||||
client.close();
|
||||
closed = true;
|
||||
}
|
||||
private static class MyLightListener implements LFXLightCollectionListener {
|
||||
private static final Logger log = LoggerFactory.getLogger(MyLightListener.class);
|
||||
@@ -254,4 +244,47 @@ public class LifxHome implements Home {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void broadcastDiscover() {
|
||||
try {
|
||||
log.info("Open Lifx client....");
|
||||
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(configuredAddress);
|
||||
InetAddress bcastInetAddr = null;
|
||||
if (networkInterface != null) {
|
||||
for (InterfaceAddress ifaceAddr : networkInterface.getInterfaceAddresses()) {
|
||||
InetAddress addr = ifaceAddr.getAddress();
|
||||
if (addr instanceof Inet4Address) {
|
||||
bcastInetAddr = ifaceAddr.getBroadcast();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bcastInetAddr != null) {
|
||||
lifxMap = new HashMap<String, LifxDevice>();
|
||||
log.info("Opening LFX Client with broadcast address: " + bcastInetAddr.getHostAddress());
|
||||
client = new LFXClient(bcastInetAddr.getHostAddress());
|
||||
client.getLights().addLightCollectionListener(new MyLightListener(lifxMap));
|
||||
client.getGroups().addGroupCollectionListener(new MyGroupListener(lifxMap));
|
||||
client.open(false);
|
||||
} else {
|
||||
log.warn("Could not open LIFX, no bcast addr available, check your upnp config address.");
|
||||
client = null;
|
||||
return;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.warn("Could not open LIFX, with IO Exception", e);
|
||||
client = null;
|
||||
return;
|
||||
} catch (InterruptedException e) {
|
||||
log.warn("Could not open LIFX, with Interruprted Exception", e);
|
||||
client = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
if(client == null)
|
||||
broadcastDiscover();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
|
||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||
import org.eclipse.paho.client.mqttv3.MqttPersistenceException;
|
||||
import org.eclipse.paho.client.mqttv3.MqttSecurityException;
|
||||
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
|
||||
import org.slf4j.Logger;
|
||||
@@ -13,11 +12,12 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class MQTTHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger(MQTTHandler.class);
|
||||
private NamedIP myConfig;
|
||||
private MqttClient myClient;
|
||||
private int qos = 1;
|
||||
|
||||
public MQTTHandler(NamedIP aConfig) {
|
||||
super();
|
||||
@@ -40,20 +40,30 @@ public class MQTTHandler {
|
||||
}
|
||||
try {
|
||||
myClient.connect(connOpts);
|
||||
} catch (MqttSecurityException e) {
|
||||
log.error("Could not connect MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e.getMessage());
|
||||
} catch (MqttException e) {
|
||||
log.error("Could not connect MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void publishMessage(String topic, String content) {
|
||||
public void publishMessage(String topic, String content, Integer qos, Boolean retain) {
|
||||
MqttMessage message = new MqttMessage(StringEscapeUtils.unescapeJava(content).getBytes());
|
||||
message.setQos(qos);
|
||||
|
||||
message.setQos(Optional.ofNullable(qos).orElse(1));
|
||||
message.setRetained(Optional.ofNullable(retain).orElse(false));
|
||||
|
||||
try {
|
||||
if(!myClient.isConnected()) {
|
||||
try {
|
||||
myClient.connect();
|
||||
} catch (MqttSecurityException e1) {
|
||||
log.error("Could not retry connect to MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e1.getMessage());
|
||||
return;
|
||||
} catch (MqttException e1) {
|
||||
log.error("Could not retry connect to MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e1.getMessage());
|
||||
return;
|
||||
}
|
||||
}
|
||||
myClient.publish(topic, message);
|
||||
} catch (MqttPersistenceException e) {
|
||||
log.error("Could not publish to MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e.getMessage());
|
||||
} catch (MqttException e) {
|
||||
log.error("Could not publish to MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e.getMessage());
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.ColorDecode;
|
||||
import com.bwssystems.HABridge.hue.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
@@ -25,25 +27,32 @@ public class MQTTHome implements Home {
|
||||
private Map<String, MQTTHandler> handlers;
|
||||
private Boolean validMqtt;
|
||||
private Gson aGsonHandler;
|
||||
private boolean closed;
|
||||
|
||||
public MQTTHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
if(!validMqtt)
|
||||
return;
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
log.debug("Shutting down MQTT handlers.");
|
||||
if(handlers != null && !handlers.isEmpty()) {
|
||||
Iterator<String> keys = handlers.keySet().iterator();
|
||||
while(keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
for (String key : handlers.keySet()) {
|
||||
handlers.get(key).shutdown();
|
||||
}
|
||||
}
|
||||
handlers = null;
|
||||
closed = false;
|
||||
}
|
||||
|
||||
public MQTTHandler getMQTTHandler(String aName) {
|
||||
@@ -78,7 +87,7 @@ public class MQTTHome implements Home {
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
String responseString = null;
|
||||
log.debug("executing HUE api request to send message to MQTT broker: " + anItem.getItem().toString());
|
||||
if (validMqtt) {
|
||||
@@ -92,6 +101,9 @@ public class MQTTHome implements Home {
|
||||
intensity, targetBri, targetBriInc, false);
|
||||
mqttObject = DeviceDataDecode.replaceDeviceData(mqttObject, device);
|
||||
mqttObject = TimeDecode.replaceTimeValue(mqttObject);
|
||||
if (colorData != null) {
|
||||
mqttObject = ColorDecode.replaceColorData(mqttObject, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false);
|
||||
}
|
||||
if (mqttObject.substring(0, 1).equalsIgnoreCase("{"))
|
||||
mqttObject = "[" + mqttObject + "]";
|
||||
MQTTMessage[] mqttMessages = aGsonHandler.fromJson(mqttObject, MQTTMessage[].class);
|
||||
@@ -108,7 +120,7 @@ public class MQTTHome implements Home {
|
||||
if (mqttHandler == null) {
|
||||
log.warn("Should not get here, no mqtt hanlder available");
|
||||
} else {
|
||||
mqttHandler.publishMessage(mqttMessages[y].getTopic(), mqttMessages[y].getMessage());
|
||||
mqttHandler.publishMessage(mqttMessages[y].getTopic(), mqttMessages[y].getMessage(), mqttMessages[y].getQos(), mqttMessages[y].getRetain());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -130,15 +142,17 @@ public class MQTTHome implements Home {
|
||||
aGsonHandler =
|
||||
new GsonBuilder()
|
||||
.create();
|
||||
handlers = new HashMap<String, MQTTHandler>();
|
||||
Iterator<NamedIP> theList = bridgeSettings.getBridgeSettingsDescriptor().getMqttaddress().getDevices().iterator();
|
||||
while(theList.hasNext()) {
|
||||
NamedIP aClientConfig = theList.next();
|
||||
handlers = new HashMap<>();
|
||||
for (NamedIP aClientConfig : bridgeSettings.getBridgeSettingsDescriptor().getMqttaddress().getDevices()) {
|
||||
MQTTHandler aHandler = new MQTTHandler(aClientConfig);
|
||||
if(aHandler != null)
|
||||
handlers.put(aClientConfig.getName(), aHandler);
|
||||
handlers.put(aClientConfig.getName(), aHandler);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ public class MQTTMessage {
|
||||
private String message;
|
||||
private Integer delay;
|
||||
private Integer count;
|
||||
private Integer qos;
|
||||
private Boolean retain;
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
@@ -36,4 +38,19 @@ public class MQTTMessage {
|
||||
public void setCount(Integer count) {
|
||||
this.count = count;
|
||||
}
|
||||
public Integer getQos() {
|
||||
return qos;
|
||||
}
|
||||
|
||||
public void setQos(Integer qos) {
|
||||
this.qos = qos;
|
||||
}
|
||||
|
||||
public Boolean getRetain() {
|
||||
return retain;
|
||||
}
|
||||
|
||||
public void setRetain(Boolean retain) {
|
||||
this.retain = retain;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.bwssystems.HABridge.plugins.openhab;
|
||||
|
||||
public class OpenHABCommand {
|
||||
private String url;
|
||||
private String command;
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
public void setCommand(String command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.bwssystems.HABridge.plugins.openhab;
|
||||
|
||||
public class OpenHABDevice {
|
||||
|
||||
private String address;
|
||||
private String name;
|
||||
private OpenHABItem item;
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public OpenHABItem getItem() {
|
||||
return item;
|
||||
}
|
||||
public void setItem(OpenHABItem item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
package com.bwssystems.HABridge.plugins.openhab;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.BridgeSettings;
|
||||
import com.bwssystems.HABridge.Home;
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.api.hue.HueError;
|
||||
import com.bwssystems.HABridge.api.hue.HueErrorResponse;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.ColorDecode;
|
||||
import com.bwssystems.HABridge.hue.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHome;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class OpenHABHome implements Home {
|
||||
private static final Logger log = LoggerFactory.getLogger(OpenHABHome.class);
|
||||
private Map<String, OpenHABInstance> openhabMap;
|
||||
private Boolean validOpenhab;
|
||||
private HTTPHandler httpClient;
|
||||
private boolean closed;
|
||||
|
||||
public OpenHABHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri, Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
|
||||
String theUrl = anItem.getItem().getAsString();
|
||||
String responseString = null;
|
||||
|
||||
if(theUrl != null && !theUrl.isEmpty()) {
|
||||
OpenHABCommand theCommand = null;
|
||||
try {
|
||||
theCommand = new Gson().fromJson(theUrl, OpenHABCommand.class);
|
||||
} catch(Exception e) {
|
||||
log.warn("Cannot parse command to OpenHAB <<<" + theUrl + ">>>", e);
|
||||
responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId,
|
||||
"Error on calling url to change device state", "/lights/"
|
||||
+ lightId + "state", null, null).getTheErrors(), HueError[].class);
|
||||
return responseString;
|
||||
}
|
||||
String intermediate = theCommand.getUrl().substring(theCommand.getUrl().indexOf("://") + 3);
|
||||
String hostPortion = intermediate.substring(0, intermediate.indexOf('/'));
|
||||
String theUrlBody = intermediate.substring(intermediate.indexOf('/') + 1);
|
||||
String hostAddr = null;
|
||||
if (hostPortion.contains(":")) {
|
||||
hostAddr = hostPortion.substring(0, intermediate.indexOf(':'));
|
||||
} else
|
||||
hostAddr = hostPortion;
|
||||
OpenHABInstance theHandler = findHandlerByAddress(hostAddr);
|
||||
if(theHandler != null) {
|
||||
String anUrl = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody,
|
||||
intensity, targetBri, targetBriInc, false);
|
||||
if (colorData != null) {
|
||||
anUrl = ColorDecode.replaceColorData(anUrl, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false);
|
||||
}
|
||||
anUrl = DeviceDataDecode.replaceDeviceData(anUrl, device);
|
||||
anUrl = TimeDecode.replaceTimeValue(anUrl);
|
||||
|
||||
String aCommand = null;
|
||||
if(theCommand.getCommand() != null && !theCommand.getCommand().isEmpty()) {
|
||||
aCommand = BrightnessDecode.calculateReplaceIntensityValue(theCommand.getCommand(),
|
||||
intensity, targetBri, targetBriInc, false);
|
||||
if (colorData != null) {
|
||||
aCommand = ColorDecode.replaceColorData(aCommand, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false);
|
||||
}
|
||||
aCommand = DeviceDataDecode.replaceDeviceData(aCommand, device);
|
||||
aCommand = TimeDecode.replaceTimeValue(aCommand);
|
||||
}
|
||||
try {
|
||||
boolean success = theHandler.callCommand(anUrl, aCommand, httpClient);
|
||||
if(!success) {
|
||||
log.warn("Comand had error to OpenHAB");
|
||||
responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId,
|
||||
"Error on calling url to change device state", "/lights/"
|
||||
+ lightId + "state", null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("Cannot send comand to OpenHAB", e);
|
||||
responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId,
|
||||
"Error on calling url to change device state", "/lights/"
|
||||
+ lightId + "state", null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
} else {
|
||||
log.warn("OpenHAB Call could not complete, no address found: " + theUrl);
|
||||
responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId,
|
||||
"Error on calling url to change device state", "/lights/"
|
||||
+ lightId + "state", null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
} else {
|
||||
log.warn("OpenHAB Call to be presented as http(s)://<ip_address>(:<port>)/payload, format of request unknown: " + theUrl);
|
||||
responseString = new Gson().toJson(HueErrorResponse.createResponse("6", "/lights/" + lightId,
|
||||
"Error on calling url to change device state", "/lights/"
|
||||
+ lightId + "state", null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
return responseString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItems(String type) {
|
||||
|
||||
if(!validOpenhab)
|
||||
return null;
|
||||
log.debug("consolidating devices for OpenHAB");
|
||||
List<OpenHABDevice> theResponse = null;
|
||||
Iterator<String> keys = openhabMap.keySet().iterator();
|
||||
List<OpenHABDevice> deviceList = new ArrayList<OpenHABDevice>();
|
||||
while(keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
theResponse = openhabMap.get(key).getDevices(httpClient);
|
||||
if(theResponse != null)
|
||||
addOpenhabDevices(deviceList, theResponse, key);
|
||||
else {
|
||||
log.warn("Cannot get devices for OpenHAB with name: " + key + ", skipping this OpenHAB.");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
private Boolean addOpenhabDevices(List<OpenHABDevice> theDeviceList, List<OpenHABDevice> theSourceList, String theKey) {
|
||||
Iterator<OpenHABDevice> devices = theSourceList.iterator();
|
||||
while(devices.hasNext()) {
|
||||
OpenHABDevice theDevice = devices.next();
|
||||
theDeviceList.add(theDevice);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Home createHome(BridgeSettings bridgeSettings) {
|
||||
openhabMap = null;
|
||||
validOpenhab = bridgeSettings.getBridgeSettingsDescriptor().isValidOpenhab();
|
||||
log.info("OpenHAB Home created." + (validOpenhab ? "" : " No OpenHABs configured."));
|
||||
if(validOpenhab) {
|
||||
openhabMap = new HashMap<String,OpenHABInstance>();
|
||||
httpClient = HTTPHome.getHandler();
|
||||
Iterator<NamedIP> theList = bridgeSettings.getBridgeSettingsDescriptor().getOpenhabaddress().getDevices().iterator();
|
||||
while(theList.hasNext() && validOpenhab) {
|
||||
NamedIP anOpenhab = theList.next();
|
||||
try {
|
||||
openhabMap.put(anOpenhab.getName(), new OpenHABInstance(anOpenhab));
|
||||
} catch (Exception e) {
|
||||
log.error("Cannot get OpenHAB (" + anOpenhab.getName() + ") setup, Exiting with message: " + e.getMessage(), e);
|
||||
validOpenhab = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private OpenHABInstance findHandlerByAddress(String hostAddress) {
|
||||
OpenHABInstance aHandler = null;
|
||||
boolean found = false;
|
||||
Iterator<String> keys = openhabMap.keySet().iterator();
|
||||
while(keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
aHandler = openhabMap.get(key);
|
||||
if(aHandler != null && aHandler.getOpenHABAddress().getIp().equals(hostAddress)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
aHandler = null;
|
||||
return aHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
log.debug("Closing Home.");
|
||||
if(!closed && validOpenhab) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
|
||||
if(httpClient != null)
|
||||
httpClient.closeHandler();
|
||||
|
||||
openhabMap = null;
|
||||
closed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.bwssystems.HABridge.plugins.openhab;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.NameValue;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class OpenHABInstance {
|
||||
private static final Logger log = LoggerFactory.getLogger(OpenHABInstance.class);
|
||||
private NamedIP theOpenHAB;
|
||||
|
||||
public OpenHABInstance(NamedIP openhabLocation) {
|
||||
super();
|
||||
theOpenHAB = openhabLocation;
|
||||
}
|
||||
|
||||
public NamedIP getOpenHABAddress() {
|
||||
return theOpenHAB;
|
||||
}
|
||||
|
||||
public void setOpenHABAddress(NamedIP openhabAddress) {
|
||||
this.theOpenHAB = openhabAddress;
|
||||
}
|
||||
|
||||
public Boolean callCommand(String aCommand, String commandData, HTTPHandler httpClient) {
|
||||
log.debug("calling OpenHAB: " + theOpenHAB.getIp() + ":" + theOpenHAB.getPort() + aCommand);
|
||||
String aUrl = null;
|
||||
NameValue[] headers = null;
|
||||
if(theOpenHAB.getSecure() != null && theOpenHAB.getSecure())
|
||||
aUrl = "https://";
|
||||
else
|
||||
aUrl = "http://";
|
||||
if(theOpenHAB.getUsername() != null && !theOpenHAB.getUsername().isEmpty() && theOpenHAB.getPassword() != null && !theOpenHAB.getPassword().isEmpty()) {
|
||||
aUrl = aUrl + theOpenHAB.getUsername() + ":" + theOpenHAB.getPassword() + "@";
|
||||
}
|
||||
aUrl = aUrl + theOpenHAB.getIp() + ":" + theOpenHAB.getPort() + "/" + aCommand;
|
||||
String theData = httpClient.doHttpRequest(aUrl, HttpPost.METHOD_NAME, "text/plain", commandData, headers);
|
||||
log.debug("call Command return is: <" + theData + ">");
|
||||
if(theData.contains("error") || theData.contains("ERROR") || theData.contains("Error"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<OpenHABDevice> getDevices(HTTPHandler httpClient) {
|
||||
List<OpenHABDevice> deviceList = null;
|
||||
OpenHABItem[] theOpenhabStates;
|
||||
String theUrl = null;
|
||||
String theData;
|
||||
NameValue[] headers = null;
|
||||
if(theOpenHAB.getSecure() != null && theOpenHAB.getSecure())
|
||||
theUrl = "https://";
|
||||
else
|
||||
theUrl = "http://";
|
||||
if(theOpenHAB.getUsername() != null && !theOpenHAB.getUsername().isEmpty() && theOpenHAB.getPassword() != null && !theOpenHAB.getPassword().isEmpty()) {
|
||||
theUrl = theUrl + theOpenHAB.getUsername() + ":" + theOpenHAB.getPassword() + "@";
|
||||
}
|
||||
theUrl = theUrl + theOpenHAB.getIp() + ":" + theOpenHAB.getPort() + "/rest/items?recursive=false";
|
||||
theData = httpClient.doHttpRequest(theUrl, HttpGet.METHOD_NAME, "application/json", null, headers);
|
||||
if(theData != null) {
|
||||
log.debug("GET OpenHAB States - data: " + theData);
|
||||
try {
|
||||
theOpenhabStates = new Gson().fromJson(theData, OpenHABItem[].class);
|
||||
if(theOpenhabStates == null) {
|
||||
log.warn("Cannot get any devices for OpenHAB " + theOpenHAB.getName() + " as response is not parsable.");
|
||||
}
|
||||
else {
|
||||
deviceList = new ArrayList<OpenHABDevice>();
|
||||
|
||||
for (int i = 0; i < theOpenhabStates.length; i++) {
|
||||
OpenHABDevice aNewOpenHABDeviceDevice = new OpenHABDevice();
|
||||
aNewOpenHABDeviceDevice.setItem(theOpenhabStates[i]);
|
||||
aNewOpenHABDeviceDevice.setAddress(theOpenHAB.getIp() + ":" + theOpenHAB.getPort());
|
||||
aNewOpenHABDeviceDevice.setName(theOpenHAB.getName());
|
||||
deviceList.add(aNewOpenHABDeviceDevice);
|
||||
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("Cannot get an devices for OpenHAB " + theOpenHAB.getName() + " Gson Parse Error.");
|
||||
}
|
||||
}
|
||||
else
|
||||
log.warn("Cannot get an devices for OpenHAB " + theOpenHAB.getName() + " http call failed.");
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
|
||||
protected void closeClient() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
|
||||
package com.bwssystems.HABridge.plugins.openhab;
|
||||
|
||||
import java.util.List;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class OpenHABItem {
|
||||
|
||||
@SerializedName("link")
|
||||
@Expose
|
||||
private String link;
|
||||
@SerializedName("state")
|
||||
@Expose
|
||||
private String state;
|
||||
@SerializedName("type")
|
||||
@Expose
|
||||
private String type;
|
||||
@SerializedName("name")
|
||||
@Expose
|
||||
private String name;
|
||||
@SerializedName("label")
|
||||
@Expose
|
||||
private String label;
|
||||
@SerializedName("category")
|
||||
@Expose
|
||||
private String category;
|
||||
@SerializedName("tags")
|
||||
@Expose
|
||||
private List<Object> tags = null;
|
||||
@SerializedName("groupNames")
|
||||
@Expose
|
||||
private List<Object> groupNames = null;
|
||||
@SerializedName("stateDescription")
|
||||
@Expose
|
||||
private StateDescription stateDescription;
|
||||
|
||||
public String getLink() {
|
||||
return link;
|
||||
}
|
||||
|
||||
public void setLink(String link) {
|
||||
this.link = link;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(String state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public void setLabel(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public void setCategory(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public List<Object> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public void setTags(List<Object> tags) {
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
public List<Object> getGroupNames() {
|
||||
return groupNames;
|
||||
}
|
||||
|
||||
public void setGroupNames(List<Object> groupNames) {
|
||||
this.groupNames = groupNames;
|
||||
}
|
||||
|
||||
public StateDescription getStateDescription() {
|
||||
return stateDescription;
|
||||
}
|
||||
|
||||
public void setStateDescription(StateDescription stateDescription) {
|
||||
this.stateDescription = stateDescription;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
|
||||
package com.bwssystems.HABridge.plugins.openhab;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class Option {
|
||||
|
||||
@SerializedName("value")
|
||||
@Expose
|
||||
private String value;
|
||||
@SerializedName("label")
|
||||
@Expose
|
||||
private String label;
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public void setLabel(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
package com.bwssystems.HABridge.plugins.openhab;
|
||||
|
||||
import java.util.List;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class StateDescription {
|
||||
|
||||
@SerializedName("pattern")
|
||||
@Expose
|
||||
private String pattern;
|
||||
@SerializedName("readOnly")
|
||||
@Expose
|
||||
private Boolean readOnly;
|
||||
@SerializedName("options")
|
||||
@Expose
|
||||
private List<Option> options = null;
|
||||
|
||||
public String getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
public void setPattern(String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
public Boolean getReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
public void setReadOnly(Boolean readOnly) {
|
||||
this.readOnly = readOnly;
|
||||
}
|
||||
|
||||
public List<Option> getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public void setOptions(List<Option> options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import com.bwssystems.HABridge.Home;
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -30,10 +31,13 @@ public class SomfyHome implements Home {
|
||||
private static final Logger log = LoggerFactory.getLogger(SomfyHome.class);
|
||||
private Map<String, SomfyInfo> somfys;
|
||||
private Boolean validSomfy;
|
||||
private boolean closed;
|
||||
|
||||
public SomfyHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
|
||||
closed = false;
|
||||
}
|
||||
|
||||
public SomfyInfo getSomfyHandler(String somfyName) {
|
||||
@@ -62,7 +66,7 @@ public class SomfyHome implements Home {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity, Integer targetBri, Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity, Integer targetBri, Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
String responseString = null;
|
||||
if (!validSomfy) {
|
||||
log.warn("Should not get here, no somfy hub available");
|
||||
@@ -113,6 +117,17 @@ public class SomfyHome implements Home {
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
somfys = null;
|
||||
closed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.bwssystems.HABridge.plugins.somfy;
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.NameValue;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHome;
|
||||
import com.bwssystems.HABridge.plugins.somfy.jsonschema2pojo.getsetup.Device;
|
||||
import com.bwssystems.HABridge.plugins.somfy.jsonschema2pojo.getsetup.GetSetup;
|
||||
import com.google.gson.Gson;
|
||||
@@ -39,7 +40,7 @@ public class SomfyInfo {
|
||||
|
||||
private void initHttpClient() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
|
||||
if(httpClient==null) {
|
||||
httpClient = new HTTPHandler();
|
||||
httpClient = HTTPHome.getHandler();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +75,7 @@ public class SomfyInfo {
|
||||
urlEncodedFormEntity.writeTo(bos);
|
||||
String body = bos.toString();
|
||||
String response = httpClient.doHttpRequest(BASE_URL + "json/login",HttpPost.METHOD_NAME, "application/x-www-form-urlencoded", body,httpHeader);
|
||||
log.debug(response);
|
||||
log.debug("Somfy login response <<<" + response + ">>>");
|
||||
}
|
||||
|
||||
private NameValue[] getHttpHeaders() {
|
||||
@@ -88,7 +89,7 @@ public class SomfyInfo {
|
||||
NameValue[] httpHeader = getHttpHeaders();
|
||||
log.info("Making SOMFY http setup call");
|
||||
String response = httpClient.doHttpRequest(BASE_URL + "json/getSetup", HttpGet.METHOD_NAME, "", "", httpHeader );
|
||||
log.debug(response);
|
||||
log.debug("Somfy getSetup response <<<" + response + ">>>");
|
||||
GetSetup setupData = new Gson().fromJson(response, GetSetup.class);
|
||||
return setupData;
|
||||
}
|
||||
@@ -97,7 +98,7 @@ public class SomfyInfo {
|
||||
login(namedIP.getUsername(), namedIP.getPassword());
|
||||
log.info("Making SOMFY http exec call");
|
||||
String response = httpClient.doHttpRequest(BASE_URL_ENDUSER + "exec/apply", HttpPost.METHOD_NAME, "application/json;charset=UTF-8", jsonToPost, getHttpHeaders());
|
||||
log.info(response);
|
||||
log.debug("Somfy exec reply response <<<" + response + ">>>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
package com.bwssystems.HABridge.plugins.somfy.jsonschema2pojo.getsetup;
|
||||
|
||||
import java.util.List;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
package com.bwssystems.HABridge.plugins.somfy.jsonschema2pojo.getsetup;
|
||||
|
||||
import java.util.List;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user