diff --git a/pom.xml b/pom.xml
index e8c94e8..b2e9c3c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
com.bwssystems.HABridge
ha-bridge
- 2.0.7-hal-g
+ 2.0.7-hal-h
jar
HA Bridge
diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java
index 40245bd..b1236ef 100644
--- a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java
+++ b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java
@@ -20,6 +20,7 @@ import com.bwssystems.util.JsonTransformer;
import com.google.gson.Gson;
public class BridgeSettings extends BackupHandler {
+ private static final Logger log = LoggerFactory.getLogger(BridgeSettings.class);
private BridgeSettingsDescriptor theBridgeSettings;
private BridgeControlDescriptor bridgeControl;
@@ -35,7 +36,6 @@ public class BridgeSettings extends BackupHandler {
return theBridgeSettings;
}
public void buildSettings() {
- Logger log = LoggerFactory.getLogger(BridgeSettings.class);
InetAddress address = null;
String addressString = null;
String theVeraAddress = null;
@@ -146,9 +146,15 @@ public class BridgeSettings extends BackupHandler {
theBridgeSettings.setUpnpDeviceDb(Configuration.DEVICE_DB_DIRECTORY);
if(theBridgeSettings.getNumberoflogmessages() == null)
- theBridgeSettings.setNumberoflogmessages(Configuration.NUMBER_OF_LOG_MESSAGES);
+ theBridgeSettings.setNumberoflogmessages(new Integer(Configuration.NUMBER_OF_LOG_MESSAGES));
+
+ if(theBridgeSettings.getNumberoflogmessages() <= 0)
+ theBridgeSettings.setNumberoflogmessages(new Integer(Configuration.NUMBER_OF_LOG_MESSAGES));
+
+ if(theBridgeSettings.getButtonsleep() == null)
+ theBridgeSettings.setButtonsleep(Integer.parseInt(Configuration.DEFAULT_BUTTON_SLEEP));
- if(theBridgeSettings.getButtonsleep() <= 0)
+ if(theBridgeSettings.getButtonsleep() < 0)
theBridgeSettings.setButtonsleep(Integer.parseInt(Configuration.DEFAULT_BUTTON_SLEEP));
theBridgeSettings.setVeraconfigured(theBridgeSettings.isValidVera());
@@ -172,11 +178,17 @@ public class BridgeSettings extends BackupHandler {
private void _loadConfig(Path aPath) {
String jsonContent = configReader(aPath);
+ try {
theBridgeSettings = new Gson().fromJson(jsonContent, BridgeSettingsDescriptor.class);
+ } catch (Exception e) {
+ log.warn("Issue loading values from file: " + aPath.toUri().toString() + ", Gson convert failed.");
+ theBridgeSettings = new BridgeSettingsDescriptor();
+ theBridgeSettings.setConfigfile(aPath.toString());
+ }
+
}
public void save(BridgeSettingsDescriptor newBridgeSettings) {
- Logger log = LoggerFactory.getLogger(BridgeSettings.class);
log.debug("Save HA Bridge settings.");
Path configPath = Paths.get(theBridgeSettings.getConfigfile());
JsonTransformer aRenderer = new JsonTransformer();
@@ -187,7 +199,6 @@ public class BridgeSettings extends BackupHandler {
private void configWriter(String content, Path filePath) {
- Logger log = LoggerFactory.getLogger(BridgeSettings.class);
if(Files.exists(filePath) && !Files.isWritable(filePath)){
log.error("Error file is not writable: " + filePath);
return;
@@ -216,8 +227,6 @@ public class BridgeSettings extends BackupHandler {
}
private String configReader(Path filePath) {
- Logger log = LoggerFactory.getLogger(BridgeSettings.class);
-
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...");
diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java
index c2c1f2a..b6066db 100644
--- a/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java
+++ b/src/main/java/com/bwssystems/HABridge/BridgeSettingsDescriptor.java
@@ -31,6 +31,7 @@ public class BridgeSettingsDescriptor {
private String haltoken;
private boolean halconfigured;
private Map whitelist;
+ private boolean settingsChanged;
public BridgeSettingsDescriptor() {
super();
@@ -40,7 +41,10 @@ public class BridgeSettingsDescriptor {
this.veraconfigured = false;
this.harmonyconfigured = false;
this.hueconfigured = false;
+ this.halconfigured = false;
this.farenheit = true;
+ this.whitelist = null;
+ this.settingsChanged = false;
}
public String getUpnpConfigAddress() {
return upnpconfigaddress;
@@ -198,6 +202,12 @@ public class BridgeSettingsDescriptor {
public void setWhitelist(Map whitelist) {
this.whitelist = whitelist;
}
+ public boolean isSettingsChanged() {
+ return settingsChanged;
+ }
+ public void setSettingsChanged(boolean settingsChanged) {
+ this.settingsChanged = settingsChanged;
+ }
public Boolean isValidVera() {
if(this.getVeraAddress() == null || this.getVeraAddress().getDevices().size() <= 0)
return false;
diff --git a/src/main/java/com/bwssystems/HABridge/HABridge.java b/src/main/java/com/bwssystems/HABridge/HABridge.java
index 7e67655..928570c 100644
--- a/src/main/java/com/bwssystems/HABridge/HABridge.java
+++ b/src/main/java/com/bwssystems/HABridge/HABridge.java
@@ -87,7 +87,8 @@ public class HABridge {
log.info("HA Bridge (v" + theVersion.getVersion() + ") reinitialization requessted....");
else
bridgeSettings.getBridgeControl().setStop(true);
-
+ if(bridgeSettings.getBridgeSettingsDescriptor().isSettingsChanged())
+ bridgeSettings.save(bridgeSettings.getBridgeSettingsDescriptor());
bridgeSettings.getBridgeControl().setReinit(false);
stop();
nestHome.closeTheNest();
diff --git a/src/main/java/com/bwssystems/HABridge/api/hue/HueConfig.java b/src/main/java/com/bwssystems/HABridge/api/hue/HueConfig.java
index e0cac47..4562a26 100644
--- a/src/main/java/com/bwssystems/HABridge/api/hue/HueConfig.java
+++ b/src/main/java/com/bwssystems/HABridge/api/hue/HueConfig.java
@@ -6,7 +6,6 @@ import java.net.SocketException;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
-import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
diff --git a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java
index 3a6d7dd..c6a0cb1 100644
--- a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java
+++ b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java
@@ -65,8 +65,10 @@ import java.net.InetAddress;
import java.net.Socket;
import java.nio.charset.Charset;
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;
@@ -146,6 +148,13 @@ public class HueMulator implements HueErrorStringSet {
log.debug("hue groups list requested: " + userId + " from " + request.ip());
response.status(HttpStatus.SC_OK);
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
+ if(validateWhitelistUser(userId, false) == null) {
+ log.debug("Valudate user, No User supplied");
+ HueErrorResponse theErrorResp = new HueErrorResponse();
+ theErrorResp.addError(new HueError(new HueErrorDetails("1", "/api/" + userId, "unauthorized user", null, null, null)));
+ return new Gson().toJson(theErrorResp.getTheErrors());
+ }
+
return "{}";
});
// http://ip_address:port/api/{userId}/groups/0 returns json objects of all groups configured
@@ -154,6 +163,13 @@ public class HueMulator implements HueErrorStringSet {
log.debug("hue group 0 list requested: " + userId + " from " + request.ip());
response.status(HttpStatus.SC_OK);
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
+ if(validateWhitelistUser(userId, false) == null) {
+ log.debug("Valudate user, No User supplied");
+ HueErrorResponse theErrorResp = new HueErrorResponse();
+ theErrorResp.addError(new HueError(new HueErrorDetails("1", "/api/" + userId, "unauthorized user", null, null, null)));
+ return new Gson().toJson(theErrorResp.getTheErrors());
+ }
+
return "[{\"error\":{\"type\":\"3\", \"address\": \"/api/" + userId + "/groups/" + "0" + "\",\"description\": \"Object not found\"}}]";
});
// http://ip_address:port/api/{userId}/scenes returns json objects of all scenes configured
@@ -162,6 +178,13 @@ public class HueMulator implements HueErrorStringSet {
log.debug("hue scenes list requested: " + userId + " from " + request.ip());
response.status(HttpStatus.SC_OK);
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
+ if(validateWhitelistUser(userId, false) == null) {
+ log.debug("Valudate user, No User supplied");
+ HueErrorResponse theErrorResp = new HueErrorResponse();
+ theErrorResp.addError(new HueError(new HueErrorDetails("1", "/api/" + userId, "unauthorized user", null, null, null)));
+ return new Gson().toJson(theErrorResp.getTheErrors());
+ }
+
return "{}";
});
// http://ip_address:port/api/{userId}/schedules returns json objects of all schedules configured
@@ -170,6 +193,13 @@ public class HueMulator implements HueErrorStringSet {
log.debug("hue schedules list requested: " + userId + " from " + request.ip());
response.status(HttpStatus.SC_OK);
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
+ if(validateWhitelistUser(userId, false) == null) {
+ log.debug("Valudate user, No User supplied");
+ HueErrorResponse theErrorResp = new HueErrorResponse();
+ theErrorResp.addError(new HueError(new HueErrorDetails("1", "/api/" + userId, "unauthorized user", null, null, null)));
+ return new Gson().toJson(theErrorResp.getTheErrors());
+ }
+
return "{}";
});
// http://ip_address:port/api/{userId}/sensors returns json objects of all sensors configured
@@ -178,6 +208,13 @@ public class HueMulator implements HueErrorStringSet {
log.debug("hue sensors list requested: " + userId + " from " + request.ip());
response.status(HttpStatus.SC_OK);
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
+ if(validateWhitelistUser(userId, false) == null) {
+ log.debug("Valudate user, No User supplied");
+ HueErrorResponse theErrorResp = new HueErrorResponse();
+ theErrorResp.addError(new HueError(new HueErrorDetails("1", "/api/" + userId, "unauthorized user", null, null, null)));
+ return new Gson().toJson(theErrorResp.getTheErrors());
+ }
+
return "{}";
});
// http://ip_address:port/api/{userId}/rules returns json objects of all rules configured
@@ -186,6 +223,13 @@ public class HueMulator implements HueErrorStringSet {
log.debug("hue rules list requested: " + userId + " from " + request.ip());
response.status(HttpStatus.SC_OK);
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
+ if(validateWhitelistUser(userId, false) == null) {
+ log.debug("Valudate user, No User supplied");
+ HueErrorResponse theErrorResp = new HueErrorResponse();
+ theErrorResp.addError(new HueError(new HueErrorDetails("1", "/api/" + userId, "unauthorized user", null, null, null)));
+ return new Gson().toJson(theErrorResp.getTheErrors());
+ }
+
return "{}";
});
// http://ip_address:port/api/{userId}/resourcelinks returns json objects of all resourcelinks configured
@@ -194,6 +238,13 @@ public class HueMulator implements HueErrorStringSet {
log.debug("hue resourcelinks list requested: " + userId + " from " + request.ip());
response.status(HttpStatus.SC_OK);
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
+ if(validateWhitelistUser(userId, false) == null) {
+ log.debug("Valudate user, No User supplied");
+ HueErrorResponse theErrorResp = new HueErrorResponse();
+ theErrorResp.addError(new HueError(new HueErrorDetails("1", "/api/" + userId, "unauthorized user", null, null, null)));
+ return new Gson().toJson(theErrorResp.getTheErrors());
+ }
+
return "{}";
});
get(HUE_CONTEXT + "/:userid/lights", "application/json", (request, response) -> {
@@ -201,15 +252,22 @@ public class HueMulator implements HueErrorStringSet {
if(bridgeSettings.isTraceupnp())
log.info("Traceupnp: hue lights list requested: " + userId + " from " + request.ip());
log.debug("hue lights list requested: " + userId + " from " + request.ip());
+ response.type("application/json; charset=utf-8");
+ response.header("Access-Control-Allow-Origin", request.headers("Origin"));
+ response.status(HttpStatus.SC_OK);
+ if(validateWhitelistUser(userId, false) == null) {
+ log.debug("Valudate user, No User supplied");
+ HueErrorResponse theErrorResp = new HueErrorResponse();
+ theErrorResp.addError(new HueError(new HueErrorDetails("1", "/api/" + userId, "unauthorized user", null, null, null)));
+ return theErrorResp.getTheErrors();
+ }
+
List deviceList = repository.findAll();
Map deviceResponseMap = new HashMap<>();
for (DeviceDescriptor device : deviceList) {
DeviceResponse deviceResponse = DeviceResponse.createResponse(device);
deviceResponseMap.put(device.getId(), deviceResponse);
}
- response.type("application/json; charset=utf-8");
- response.header("Access-Control-Allow-Origin", request.headers("Origin"));
- response.status(HttpStatus.SC_OK);
return deviceResponseMap;
} , new JsonTransformer());
@@ -238,8 +296,9 @@ public class HueMulator implements HueErrorStringSet {
aDeviceType = aNewUser.getDevicetype();
}
if(newUser == null)
- newUser = getNewUserID(request.ip());
+ newUser = getNewUserID();
+ validateWhitelistUser(newUser, false);
if(aDeviceType == null)
aDeviceType = "";
if(bridgeSettings.isTraceupnp())
@@ -276,8 +335,8 @@ public class HueMulator implements HueErrorStringSet {
aDeviceType = aNewUser.getDevicetype();
}
if(newUser == null)
- newUser = getNewUserID(request.ip());
-
+ newUser = getNewUserID();
+ validateWhitelistUser(newUser, false);
if(aDeviceType == null)
aDeviceType = "";
log.debug("HH trace: hue api user create requested for device type: " + aDeviceType + " and username: " + newUser);
@@ -303,14 +362,20 @@ public class HueMulator implements HueErrorStringSet {
// http://ip_address:port/api/{userId}/config returns json objects for the config
get(HUE_CONTEXT + "/:userid/config", "application/json", (request, response) -> {
String userId = request.params(":userid");
- if(bridgeSettings.isTraceupnp())
- log.info("Traceupnp: hue api/:userid/config config requested: " + userId + " from " + request.ip());
- log.debug("hue api config requested: " + userId + " from " + request.ip());
- HueApiResponse apiResponse = new HueApiResponse("Philips hue", bridgeSettings.getUpnpConfigAddress(), bridgeSettings.getWhitelist());
-
response.type("application/json; charset=utf-8");
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
response.status(HttpStatus.SC_OK);
+ if(bridgeSettings.isTraceupnp())
+ log.info("Traceupnp: hue api/:userid/config config requested: " + userId + " from " + request.ip());
+ log.debug("hue api config requested: " + userId + " from " + request.ip());
+ if(validateWhitelistUser(userId, true) == null) {
+ log.debug("Valudate user, No User supplied, returning public config");
+ HuePublicConfig apiResponse = HuePublicConfig.createConfig("Philips hue", bridgeSettings.getUpnpConfigAddress());
+ return apiResponse;
+ }
+
+ HueApiResponse apiResponse = new HueApiResponse("Philips hue", bridgeSettings.getUpnpConfigAddress(), bridgeSettings.getWhitelist());
+
return apiResponse.getConfig();
}, new JsonTransformer());
@@ -321,28 +386,25 @@ public class HueMulator implements HueErrorStringSet {
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
response.type("application/json; charset=utf-8");
response.status(HttpStatus.SC_OK);
- if(userId == null || userId.equalsIgnoreCase("undefined") || userId.equalsIgnoreCase("null") || userId.equalsIgnoreCase("")) {
- log.debug("hue api full state requested: " + userId + " from " + request.ip() + ". No User supplied");
+ log.debug("hue api full state requested: " + userId + " from " + request.ip());
+ if(validateWhitelistUser(userId, false) == null) {
+ log.debug("Valudate user, No User supplied");
HueErrorResponse theErrorResp = new HueErrorResponse();
theErrorResp.addError(new HueError(new HueErrorDetails("1", "/api/" + userId, "unauthorized user", null, null, null)));
return theErrorResp.getTheErrors();
}
- else
- log.debug("hue api full state requested: " + userId + " from " + request.ip());
- List descriptorList = repository.findAll();
- if (descriptorList == null) {
- response.status(HttpStatus.SC_NOT_FOUND);
- return null;
- }
+
+ HueApiResponse apiResponse = new HueApiResponse("Philips hue", bridgeSettings.getUpnpConfigAddress(), bridgeSettings.getWhitelist());
Map deviceList = new HashMap<>();
-
- descriptorList.forEach(descriptor -> {
- DeviceResponse deviceResponse = DeviceResponse.createResponse(descriptor);
- deviceList.put(descriptor.getId(), deviceResponse);
- }
- );
- HueApiResponse apiResponse = new HueApiResponse("Philips hue", bridgeSettings.getUpnpConfigAddress(), bridgeSettings.getWhitelist());
- apiResponse.setLights(deviceList);
+ List descriptorList = repository.findAll();
+ if (descriptorList != null) {
+ descriptorList.forEach(descriptor -> {
+ DeviceResponse deviceResponse = DeviceResponse.createResponse(descriptor);
+ deviceList.put(descriptor.getId(), deviceResponse);
+ }
+ );
+ apiResponse.setLights(deviceList);
+ }
return apiResponse;
}, new JsonTransformer());
@@ -355,7 +417,14 @@ public class HueMulator implements HueErrorStringSet {
response.type("application/json; charset=utf-8");
response.status(HttpStatus.SC_OK);
log.debug("hue light requested: " + lightId + " for user: " + userId + " from " + request.ip());
- DeviceDescriptor device = repository.findOne(lightId);
+ if(validateWhitelistUser(userId, false) == null) {
+ log.debug("Valudate user, No User supplied");
+ HueErrorResponse theErrorResp = new HueErrorResponse();
+ theErrorResp.addError(new HueError(new HueErrorDetails("1", "/api/" + userId, "unauthorized user", null, null, null)));
+ return theErrorResp.getTheErrors();
+ }
+
+ DeviceDescriptor device = repository.findOne(lightId);
if (device == null) {
response.status(HttpStatus.SC_NOT_FOUND);
HueErrorResponse theErrorResp = new HueErrorResponse();
@@ -392,6 +461,12 @@ public class HueMulator implements HueErrorStringSet {
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
response.type("application/json; charset=utf-8");
response.status(HttpStatus.SC_OK);
+ if(validateWhitelistUser(userId, false) == null) {
+ log.debug("Valudate user, No User supplied");
+ HueErrorResponse theErrorResp = new HueErrorResponse();
+ theErrorResp.addError(new HueError(new HueErrorDetails("1", "/api/" + userId, "unauthorized user", null, null, null)));
+ return new Gson().toJson(theErrorResp.getTheErrors());
+ }
theStateChanges = new Gson().fromJson(request.body(), StateChangeBody.class);
if (theStateChanges == null) {
log.warn("Could not parse state change body. Light state not changed.");
@@ -469,6 +544,12 @@ public class HueMulator implements HueErrorStringSet {
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
response.type("application/json; charset=utf-8");
response.status(HttpStatus.SC_OK);
+ if(validateWhitelistUser(userId, false) == null) {
+ log.debug("Valudate user, No User supplied");
+ HueErrorResponse theErrorResp = new HueErrorResponse();
+ theErrorResp.addError(new HueError(new HueErrorDetails("1", "/api/" + userId, "unauthorized user", null, null, null)));
+ return new Gson().toJson(theErrorResp.getTheErrors());
+ }
theStateChanges = new Gson().fromJson(request.body(), StateChangeBody.class);
if (theStateChanges == null) {
@@ -1064,8 +1145,8 @@ public class HueMulator implements HueErrorStringSet {
return responseString;
}
- private String getNewUserID(String seed) {
- UUID uid = UUID.fromString(seed);
+ private String getNewUserID() {
+ UUID uid = UUID.randomUUID();
StringTokenizer st = new StringTokenizer(uid.toString(), "-");
String newUser = "";
while(st.hasMoreTokens()) {
@@ -1074,8 +1155,35 @@ public class HueMulator implements HueErrorStringSet {
return newUser;
}
- private String lookupWhitelistUser() {
-
+ private String validateWhitelistUser(String aUser, boolean strict) {
+ if(aUser == null ||aUser.equalsIgnoreCase("undefined") || aUser.equalsIgnoreCase("null") || aUser.equalsIgnoreCase(""))
+ return null;
+
+ String validUser = null;
+ boolean found = false;
+ if(bridgeSettings.getWhitelist() != null) {
+ Set theUserIds = bridgeSettings.getWhitelist().keySet();
+ Iterator userIterator = theUserIds.iterator();
+ while(userIterator.hasNext()) {
+ validUser = userIterator.next();
+ if(validUser.equals(aUser))
+ found = true;
+ }
+ }
+
+ if(!found && strict)
+ return null;
+
+ if(!found) {
+ if(bridgeSettings.getWhitelist() == null) {
+ Map awhitelist = new HashMap<>();
+ bridgeSettings.setWhitelist(awhitelist);
+ }
+ bridgeSettings.getWhitelist().put(aUser, WhitelistEntry.createEntry("auto insert user"));
+ bridgeSettings.setSettingsChanged(true);
+
+ }
+ return aUser;
}
@Override
public void setErrorString(String anError) {
diff --git a/src/main/java/com/bwssystems/hal/HalHome.java b/src/main/java/com/bwssystems/hal/HalHome.java
index 0546339..17c8169 100644
--- a/src/main/java/com/bwssystems/hal/HalHome.java
+++ b/src/main/java/com/bwssystems/hal/HalHome.java
@@ -43,8 +43,10 @@ public class HalHome {
theResponse = hals.get(key).getLights();
if(theResponse != null)
addHalDevices(deviceList, theResponse, key);
- else
- log.warn("Cannot get lights for Hal with name: " + key);
+ else {
+ log.warn("Cannot get lights for Hal with name: " + key + ", skipping this HAL.");
+ continue;
+ }
theResponse = hals.get(key).getAppliances();
if(theResponse != null)
addHalDevices(deviceList, theResponse, key);
diff --git a/src/main/java/com/bwssystems/hal/HalInfo.java b/src/main/java/com/bwssystems/hal/HalInfo.java
index 4acd36b..450fa2f 100644
--- a/src/main/java/com/bwssystems/hal/HalInfo.java
+++ b/src/main/java/com/bwssystems/hal/HalInfo.java
@@ -143,6 +143,8 @@ public class HalInfo {
String theUrl = null;
String theData;
+ if(theIrDevices == null)
+ return null;
Iterator theHalDevices = theIrDevices.iterator();
deviceList = new ArrayList();
while (theHalDevices.hasNext()) {