mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-16 18:24:36 +00:00
Fixed enable rooms for Alexa. Removed huemulator redirect for Spark.
Added Link management as links are now stored with IP.
This commit is contained in:
4
pom.xml
4
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>com.bwssystems.HABridge</groupId>
|
||||
<artifactId>ha-bridge</artifactId>
|
||||
<version>5.0.0a</version>
|
||||
<version>5.1.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HA Bridge</name>
|
||||
@@ -63,7 +63,7 @@
|
||||
<dependency>
|
||||
<groupId>com.sparkjava</groupId>
|
||||
<artifactId>spark-core</artifactId>
|
||||
<version>2.3</version>
|
||||
<version>2.7.1</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
|
||||
@@ -205,6 +205,12 @@ public class BridgeSecurity {
|
||||
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;
|
||||
|
||||
@@ -62,7 +62,7 @@ public class HABridge {
|
||||
// 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()));
|
||||
initExceptionHandler((e) -> HABridge.theExceptionHandler(e, bridgeSettings.getBridgeSettingsDescriptor().getServerPort()));
|
||||
if(!bridgeSettings.getBridgeControl().isReinit())
|
||||
init();
|
||||
bridgeSettings.getBridgeControl().setReinit(false);
|
||||
|
||||
@@ -8,6 +8,7 @@ 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;
|
||||
@@ -16,11 +17,13 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Timer;
|
||||
import java.util.Base64;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
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,6 +31,7 @@ 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;
|
||||
@@ -295,6 +299,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);
|
||||
|
||||
@@ -48,10 +48,7 @@ public class DeviceResource {
|
||||
public DeviceResource(BridgeSettings theSettings, HomeManager aHomeManager) {
|
||||
bridgeSettings = theSettings;
|
||||
this.deviceRepository = new DeviceRepository(bridgeSettings.getBridgeSettingsDescriptor().getUpnpDeviceDb());
|
||||
if(bridgeSettings.getBridgeSettingsDescriptor().isUserooms())
|
||||
this.groupRepository = new GroupRepository(bridgeSettings.getBridgeSettingsDescriptor().getUpnpGroupDb());
|
||||
else
|
||||
this.groupRepository = null;
|
||||
homeManager = aHomeManager;
|
||||
aGsonHandler = new GsonBuilder().create();
|
||||
setupEndpoints();
|
||||
|
||||
@@ -76,10 +76,11 @@ public class HueMulator {
|
||||
public void setupServer() {
|
||||
log.info("Hue emulator service started....");
|
||||
before(HUE_CONTEXT + "/*", (request, response) -> {
|
||||
String path = request.pathInfo();
|
||||
if (path.endsWith("/")) { // it should work with or without a trailing slash
|
||||
response.redirect(path.substring(0, path.length() - 1));
|
||||
}
|
||||
// This currently causes an error with Spark replies
|
||||
// String path = request.pathInfo();
|
||||
// if (path.endsWith("/")) { // it should work with or without a trailing slash
|
||||
// response.redirect(path.substring(0, path.length() - 1));
|
||||
// }
|
||||
log.debug("HueMulator " + request.requestMethod() + " called on api/* with request <<<" + request.pathInfo() + ">>>, and body <<<" + request.body() + ">>>");
|
||||
if(bridgeSettingMaster.getBridgeSecurity().isSecure()) {
|
||||
String pathInfo = request.pathInfo();
|
||||
@@ -127,12 +128,7 @@ public class HueMulator {
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.type("application/json");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
if(bridgeSettings.isUserooms()) {
|
||||
return addGroup(request.params(":userid"), request.ip(), request.body());
|
||||
} else {
|
||||
log.debug("group add requested from (No Use Rooms) " + request.ip() + " user " + request.params(":userid") + " with body " + request.body());
|
||||
return "[{\"success\":{\"id\":\"1\"}}]";
|
||||
}
|
||||
});
|
||||
// http://ip_address:port/api/:userid/groups/<groupid>
|
||||
// delete a group
|
||||
@@ -140,12 +136,7 @@ public class HueMulator {
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.type("application/json");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
if(bridgeSettings.isUserooms()) {
|
||||
return deleteGroup(request.params(":userid"), request.params(":groupid"), request.ip());
|
||||
} else {
|
||||
log.debug("delete to groups API from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body());
|
||||
return "[{\"error\":{\"address\": \"/groups/0/action/scene\", \"type\":7, \"description\": \"invalid value, dummy for parameter, scene\"}}]";
|
||||
}
|
||||
});
|
||||
// http://ip_address:port/api/:userid/groups/<groupid>
|
||||
// modify a single group
|
||||
@@ -153,12 +144,7 @@ public class HueMulator {
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.type("application/json");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
if(bridgeSettings.isUserooms()) {
|
||||
return modifyGroup(request.params(":userid"), request.params(":groupid"), request.ip(), request.body());
|
||||
} else {
|
||||
log.debug("put to groups API from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body());
|
||||
return "[{\"error\":{\"address\": \"/groups/0/action/scene\", \"type\":7, \"description\": \"invalid value, dummy for parameter, scene\"}}]";
|
||||
}
|
||||
});
|
||||
// http://ip_address:port/api/:userid/groups/<groupid>/action
|
||||
// group acions
|
||||
@@ -166,12 +152,7 @@ public class HueMulator {
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.type("application/json");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
if(bridgeSettings.isUserooms()) {
|
||||
return changeGroupState(request.params(":userid"), request.params(":groupid"), request.body(), request.ip(), false);
|
||||
} else {
|
||||
log.debug("put action to groups API from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body());
|
||||
return "[{\"error\":{\"address\": \"/groups/0/action/scene\", \"type\":7, \"description\": \"invalid value, dummy for parameter, scene\"}}]";
|
||||
}
|
||||
});
|
||||
// http://ip_address:port/api/{userId}/scenes returns json objects of
|
||||
// all scenes configured
|
||||
@@ -1022,7 +1003,7 @@ public class HueMulator {
|
||||
if (theErrors != null)
|
||||
return theErrors;
|
||||
|
||||
if (Integer.parseInt(lightId) >= 10000) {
|
||||
if (bridgeSettings.isUserooms() && Integer.parseInt(lightId) >= 10000) {
|
||||
GroupDescriptor group = groupRepository.findOne(String.valueOf(Integer.parseInt(lightId) - 10000));
|
||||
return DeviceResponse.createResponseForVirtualLight(group);
|
||||
}
|
||||
|
||||
@@ -277,6 +277,7 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
return $http.post(this.state.huebase, "{\"devicetype\":\"test_ha_bridge\"}").then(
|
||||
function (response) {
|
||||
self.state.testuser = response.data[0].success.username;
|
||||
self.getWhitelist();
|
||||
},
|
||||
function (error) {
|
||||
if (error.status === 401)
|
||||
@@ -318,7 +319,7 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
if (error.status === 401)
|
||||
$rootScope.$broadcast('securityReinit', 'done');
|
||||
else
|
||||
self.displayWarn("Update ecurity settings Error: ", error);
|
||||
self.displayWarn("Update security settings Error: ", error);
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -410,6 +411,29 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
);
|
||||
};
|
||||
|
||||
this.getWhitelist = function () {
|
||||
return $http.get(this.state.systemsbase + "/whitelist").then(
|
||||
function (response) {
|
||||
self.state.whitelist = response.data;
|
||||
},
|
||||
function (error) {
|
||||
self.displayWarn("Cannot get swhitelist: ", error);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
this.setWhitelist = function (whitelist) {
|
||||
return $http.post(this.state.systemsbase + "/setwhitelist", whitelist ).then(
|
||||
function (response) {
|
||||
self.state.whitelist = response.data;
|
||||
self.displaySuccess("Updated whitelist.")
|
||||
},
|
||||
function (error) {
|
||||
self.displayWarn("Update whitelist Error: ", error);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
this.aContainsB = function (a, b) {
|
||||
return a.indexOf(b) >= 0;
|
||||
}
|
||||
@@ -1141,6 +1165,18 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
|
||||
};
|
||||
|
||||
this.saveSettingsNoReinit = function () {
|
||||
return $http.put(this.state.systemsbase + "/settings", this.state.settings).then(
|
||||
function (response) {
|
||||
self.displaySuccess("Save Settings completed.");
|
||||
},
|
||||
function (error) {
|
||||
self.displayWarn("Save Settings Error: ", error);
|
||||
}
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
this.backupSettings = function (afilename) {
|
||||
return $http.put(this.state.systemsbase + "/backup/create", {
|
||||
filename: afilename
|
||||
@@ -1699,6 +1735,40 @@ app.controller('SecurityDialogCtrl', function ($scope, bridgeService, ngDialog)
|
||||
};
|
||||
});
|
||||
|
||||
app.controller('ManageLinksDialogCtrl', function ($scope, bridgeService, ngDialog) {
|
||||
bridgeService.getWhitelist();
|
||||
$scope.whitelist = bridgeService.state.whitelist;
|
||||
|
||||
$scope.setWhitelist = function () {
|
||||
bridgeService.setWhitelist($scope.whitelist);
|
||||
ngDialog.close('ngdialog1');
|
||||
};
|
||||
|
||||
$scope.delEntry = function (anEntry) {
|
||||
for(var key in $scope.whitelist) {
|
||||
if ($scope.whitelist.hasOwnProperty(key)) {
|
||||
var theEntry = $scope.whitelist[key];
|
||||
if(theEntry.name === anEntry) {
|
||||
delete $scope.whitelist[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.refresh = function () {
|
||||
bridgeService.getWhitelist();
|
||||
$scope.whitelist = bridgeService.state.whitelist;
|
||||
}
|
||||
|
||||
$scope.delAll = function () {
|
||||
$scope.whitelist = null;
|
||||
};
|
||||
|
||||
$scope.dismissDialog = function () {
|
||||
ngDialog.close('ngdialog1');
|
||||
};
|
||||
});
|
||||
|
||||
app.controller('LogsController', function ($scope, $location, bridgeService) {
|
||||
bridgeService.viewLogs();
|
||||
$scope.bridge = bridgeService.state;
|
||||
@@ -1807,6 +1877,13 @@ app.controller('ViewingController', function ($scope, $location, bridgeService,
|
||||
$scope.pushLinkButton = function() {
|
||||
bridgeService.pushLinkButton();
|
||||
};
|
||||
$scope.manageLinksButton = function() {
|
||||
ngDialog.open({
|
||||
template: 'views/managelinksdialog.html',
|
||||
controller: 'ManageLinksDialogCtrl',
|
||||
className: 'ngdialog-theme-default'
|
||||
});
|
||||
};
|
||||
$scope.backupDeviceDb = function (optionalbackupname) {
|
||||
bridgeService.backupDeviceDb(optionalbackupname);
|
||||
};
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
<div class="form-group">
|
||||
<button class="btn btn-primary" type="submit" ng-click="renumberDevices()">Renumber Devices</button>
|
||||
<button ng-if="bridge.securityInfo.useLinkButton" class="btn btn-primary" type="submit" ng-click="pushLinkButton()">Link</button>
|
||||
<button class="btn btn-primary" type="submit" ng-click="manageLinksButton()">Manage Links</button>
|
||||
<label for="device-ip-filter">Show devices visible to: </label>
|
||||
<input type="text" id="device-ip-filter" style="width:150px"
|
||||
ng-model="bridge.state.filterDevicesByIpAddress" placeholder="">
|
||||
|
||||
32
src/main/resources/public/views/managelinksdialog.html
Normal file
32
src/main/resources/public/views/managelinksdialog.html
Normal file
@@ -0,0 +1,32 @@
|
||||
<div class="form-container ngdialog-message" ng-controller="ManageLinksDialogCtrl">
|
||||
|
||||
<form name="manageLinksForm" role="form">
|
||||
<legend class="form-label">Manage Links</legend>
|
||||
<div>
|
||||
<scrollable-table watch="whitelist">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Create Date</th>
|
||||
<th>Manage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="linkItem in whitelist">
|
||||
<td>{{linkItem.name}}</td>
|
||||
<td>{{linkItem.createDate}}</td>
|
||||
<td><button class="btn btn-danger" type="submit"
|
||||
ng-click="delEntry(linkItem.name)">Del</button></td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table></td>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="button" class="btn btn-success" ng-click="dismissDialog()" autofocus>Dismiss</button>
|
||||
<button type="button" class="btn btn-info" ng-click="refresh()" autofocus>Refresh</button>
|
||||
<button type="button" class="btn btn-warning" ng-click="setWhitelist()" autofocus>Save</button>
|
||||
<button type="button" class="btn btn-danger" ng-click="delAll()" autofocus>Clear All</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
Reference in New Issue
Block a user