mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-18 16:17:30 +00:00
Added backup and restore for device db functionality. Testing multi
button press for harmony.
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>com.bwssystems.HABridge</groupId>
|
||||
<artifactId>ha-bridge</artifactId>
|
||||
<version>1.3.1a</version>
|
||||
<version>1.3.1b</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HA Bridge</name>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.bwssystems.HABridge.dao;
|
||||
|
||||
public class BackupFilename {
|
||||
private String filename;
|
||||
|
||||
public String getFilename() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
public void setFilename(String filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,17 @@ package com.bwssystems.HABridge.dao;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
@@ -33,8 +38,16 @@ public class DeviceRepository {
|
||||
|
||||
public DeviceRepository(String deviceDb) {
|
||||
super();
|
||||
repositoryPath = Paths.get(deviceDb);
|
||||
String jsonContent = repositoryReader(repositoryPath);
|
||||
_loadRepository(deviceDb);
|
||||
}
|
||||
|
||||
private void _loadRepository(String aFilePath){
|
||||
repositoryPath = Paths.get(aFilePath);
|
||||
_loadRepository(repositoryPath);
|
||||
}
|
||||
|
||||
private void _loadRepository(Path aPath){
|
||||
String jsonContent = repositoryReader(aPath);
|
||||
devices = new HashMap<String, DeviceDescriptor>();
|
||||
|
||||
if(jsonContent != null)
|
||||
@@ -47,6 +60,7 @@ public class DeviceRepository {
|
||||
put(theDevice.getId(), theDevice);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public List<DeviceDescriptor> findAll() {
|
||||
@@ -79,6 +93,66 @@ public class DeviceRepository {
|
||||
log.debug("Save device: " + aDescriptor.getName());
|
||||
}
|
||||
|
||||
public String backup(String aFilename) {
|
||||
if(aFilename == null || aFilename.equalsIgnoreCase("")) {
|
||||
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
|
||||
aFilename = "devicedb-" + dateFormat.format(Calendar.getInstance().getTime()) + ".bk";
|
||||
}
|
||||
else
|
||||
aFilename = aFilename + ".bk";
|
||||
try {
|
||||
Files.copy(repositoryPath, FileSystems.getDefault().getPath(repositoryPath.getParent().toString(), aFilename), StandardCopyOption.COPY_ATTRIBUTES);
|
||||
} catch (IOException e) {
|
||||
log.error("Could not backup to file: " + aFilename + " message: " + e.getMessage(), e);
|
||||
}
|
||||
log.debug("Backup repository: " + aFilename);
|
||||
return aFilename;
|
||||
}
|
||||
|
||||
public String deleteBackup(String aFilename) {
|
||||
log.debug("Delete backup repository: " + aFilename);
|
||||
try {
|
||||
Files.delete(FileSystems.getDefault().getPath(repositoryPath.getParent().toString(), aFilename));
|
||||
} catch (IOException e) {
|
||||
log.error("Could not delete file: " + aFilename + " message: " + e.getMessage(), e);
|
||||
}
|
||||
return aFilename;
|
||||
}
|
||||
|
||||
public String restoreBackup(String aFilename) {
|
||||
log.debug("Restore backup repository: " + aFilename);
|
||||
try {
|
||||
Path target = null;
|
||||
if(Files.exists(repositoryPath)) {
|
||||
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
|
||||
target = FileSystems.getDefault().getPath(repositoryPath.getParent().toString(), "devicedb-" + dateFormat.format(Calendar.getInstance().getTime()) + ".bk");
|
||||
Files.move(repositoryPath, target);
|
||||
}
|
||||
Files.copy(FileSystems.getDefault().getPath(repositoryPath.getParent().toString(), aFilename), repositoryPath, StandardCopyOption.COPY_ATTRIBUTES);
|
||||
} catch (IOException e) {
|
||||
log.error("Error restoring the file: " + aFilename + " message: " + e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
_loadRepository(repositoryPath);
|
||||
return aFilename;
|
||||
}
|
||||
|
||||
public List<String> getBackups() {
|
||||
List<String> theFilenames = new ArrayList<String>();
|
||||
Path dir = repositoryPath.getParent();
|
||||
try (DirectoryStream<Path> stream =
|
||||
Files.newDirectoryStream(dir, "*.{bk}")) {
|
||||
for (Path entry: stream) {
|
||||
theFilenames.add(entry.getFileName().toString());
|
||||
}
|
||||
} catch (IOException x) {
|
||||
// IOException can never be thrown by the iteration.
|
||||
// In this snippet, it can // only be thrown by newDirectoryStream.
|
||||
log.error("Issue getting direcotyr listing for backups - " + x.getMessage());
|
||||
}
|
||||
return theFilenames;
|
||||
}
|
||||
|
||||
public String delete(DeviceDescriptor aDescriptor) {
|
||||
if (aDescriptor != null) {
|
||||
devices.remove(aDescriptor.getId());
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.slf4j.LoggerFactory;
|
||||
import com.bwssystems.HABridge.BridgeSettings;
|
||||
import com.bwssystems.HABridge.JsonTransformer;
|
||||
import com.bwssystems.HABridge.Version;
|
||||
import com.bwssystems.HABridge.dao.BackupFilename;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.dao.DeviceRepository;
|
||||
import com.bwssystems.NestBridge.NestHome;
|
||||
@@ -234,5 +235,66 @@ public class DeviceResource {
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return nestHome.getItems();
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/backup/available", "application/json", (request, response) -> {
|
||||
log.debug("Get backup filenames");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return deviceRepository.getBackups();
|
||||
}, new JsonTransformer());
|
||||
|
||||
// http://ip_address:port/api/devices/backup/create CORS request
|
||||
options(API_CONTEXT + "/backup/create", "application/json", (request, response) -> {
|
||||
response.status(HttpStatus.SC_OK);
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.header("Access-Control-Allow-Methods", "PUT");
|
||||
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
|
||||
response.header("Content-Type", "text/html; charset=utf-8");
|
||||
return "";
|
||||
});
|
||||
put (API_CONTEXT + "/backup/create", "application/json", (request, response) -> {
|
||||
log.debug("Create backup: " + request.body());
|
||||
BackupFilename aFilename = new Gson().fromJson(request.body(), BackupFilename.class);
|
||||
BackupFilename returnFilename = new BackupFilename();
|
||||
returnFilename.setFilename(deviceRepository.backup(aFilename.getFilename()));
|
||||
return returnFilename;
|
||||
}, new JsonTransformer());
|
||||
|
||||
// http://ip_address:port/api/devices/backup/delete CORS request
|
||||
options(API_CONTEXT + "/backup/delete", "application/json", (request, response) -> {
|
||||
response.status(HttpStatus.SC_OK);
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.header("Access-Control-Allow-Methods", "POST");
|
||||
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
|
||||
response.header("Content-Type", "text/html; charset=utf-8");
|
||||
return "";
|
||||
});
|
||||
post (API_CONTEXT + "/backup/delete", "application/json", (request, response) -> {
|
||||
log.debug("Delete backup: " + request.body());
|
||||
BackupFilename aFilename = new Gson().fromJson(request.body(), BackupFilename.class);
|
||||
if(aFilename != null)
|
||||
deviceRepository.deleteBackup(aFilename.getFilename());
|
||||
else
|
||||
log.warn("No filename given for delete backup.");
|
||||
return null;
|
||||
}, new JsonTransformer());
|
||||
|
||||
// http://ip_address:port/api/devices/backup/restore CORS request
|
||||
options(API_CONTEXT + "/backup/restore", "application/json", (request, response) -> {
|
||||
response.status(HttpStatus.SC_OK);
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.header("Access-Control-Allow-Methods", "POST");
|
||||
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
|
||||
response.header("Content-Type", "text/html; charset=utf-8");
|
||||
return "";
|
||||
});
|
||||
post (API_CONTEXT + "/backup/restore", "application/json", (request, response) -> {
|
||||
log.debug("Restore backup: " + request.body());
|
||||
BackupFilename aFilename = new Gson().fromJson(request.body(), BackupFilename.class);
|
||||
if(aFilename != null)
|
||||
deviceRepository.restoreBackup(aFilename.getFilename());
|
||||
else
|
||||
log.warn("No filename given for restore backup.");
|
||||
return null;
|
||||
}, new JsonTransformer());
|
||||
}
|
||||
}
|
||||
@@ -348,7 +348,7 @@ public class HueMulator {
|
||||
else {
|
||||
for(int i = 0; i < deviceButtons.length; i++) {
|
||||
if( i > 0)
|
||||
Thread.sleep(500);
|
||||
Thread.sleep(100);
|
||||
log.debug("pressing button: " + deviceButtons[i].getDevice() + " - " + deviceButtons[i].getButton() + " - iteration: " + String.valueOf(i));
|
||||
myHarmony.pressButton(deviceButtons[i]);
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ app.factory('BridgeSettings', function() {
|
||||
app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
var self = this;
|
||||
self.BridgeSettings = BridgeSettings;
|
||||
this.state = {base: window.location.origin + "/api/devices", upnpbase: window.location.origin + "/upnp/settings", huebase: window.location.origin + "/api", devices: [], device: [], error: "", showVera: false, showHarmony: false, showNest: false, habridgeversion: ""};
|
||||
this.state = {base: window.location.origin + "/api/devices", upnpbase: window.location.origin + "/upnp/settings", huebase: window.location.origin + "/api", backups: [], devices: [], device: [], error: "", showVera: false, showHarmony: false, showNest: false, habridgeversion: ""};
|
||||
|
||||
this.viewDevices = function () {
|
||||
this.state.error = "";
|
||||
@@ -192,11 +192,26 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
);
|
||||
};
|
||||
|
||||
this.viewBackups = function () {
|
||||
this.state.error = "";
|
||||
return $http.get(this.state.base + "/backup/available").then(
|
||||
function (response) {
|
||||
self.state.backups = response.data;
|
||||
},
|
||||
function (error) {
|
||||
if (error.data) {
|
||||
$window.alert("Get Backups Error: " + error.data.message);
|
||||
} else {
|
||||
$window.alert("Get Backups Error: unknown");
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
this.viewNestItems = function () {
|
||||
this.state.error = "";
|
||||
if(!this.state.showNest)
|
||||
return;
|
||||
this.state.error = "";
|
||||
return $http.get(this.state.base + "/nest/items").then(
|
||||
function (response) {
|
||||
self.state.nestitems = response.data;
|
||||
@@ -215,7 +230,6 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
this.state.error = "";
|
||||
if(!this.state.showVera)
|
||||
return;
|
||||
this.state.error = "";
|
||||
return $http.get(this.state.base + "/vera/devices").then(
|
||||
function (response) {
|
||||
self.state.veradevices = response.data;
|
||||
@@ -361,6 +375,58 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
}
|
||||
};
|
||||
|
||||
this.backupDeviceDb = function (afilename) {
|
||||
this.state.error = "";
|
||||
return $http.put(this.state.base + "/backup/create", {
|
||||
filename: afilename
|
||||
}).then(
|
||||
function (response) {
|
||||
self.viewBackups();
|
||||
},
|
||||
function (error) {
|
||||
if (error.data) {
|
||||
self.state.error = error.data.message;
|
||||
}
|
||||
$window.alert("Backup Device Db Error: unknown");
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
this.restoreBackup = function (afilename) {
|
||||
this.state.error = "";
|
||||
return $http.post(this.state.base + "/backup/restore", {
|
||||
filename: afilename
|
||||
}).then(
|
||||
function (response) {
|
||||
self.viewBackups();
|
||||
self.viewDevices();
|
||||
},
|
||||
function (error) {
|
||||
if (error.data) {
|
||||
self.state.error = error.data.message;
|
||||
}
|
||||
$window.alert("Backup Db Restore Error: unknown");
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
this.deleteBackup = function (afilename) {
|
||||
this.state.error = "";
|
||||
return $http.post(this.state.base + "/backup/delete", {
|
||||
filename: afilename
|
||||
}).then(
|
||||
function (response) {
|
||||
self.viewBackups();
|
||||
},
|
||||
function (error) {
|
||||
if (error.data) {
|
||||
self.state.error = error.data.message;
|
||||
}
|
||||
$window.alert("Backup Db Frlryr Error: unknown");
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
this.deleteDevice = function (id) {
|
||||
this.state.error = "";
|
||||
return $http.delete(this.state.base + "/" + id).then(
|
||||
@@ -417,9 +483,13 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
|
||||
|
||||
$scope.BridgeSettings = bridgeService.BridgeSettings;
|
||||
bridgeService.viewDevices();
|
||||
bridgeService.viewBackups();
|
||||
$scope.bridge = bridgeService.state;
|
||||
$scope.optionalbackupname = "";
|
||||
$scope.visible = false;
|
||||
$scope.imgUrl = "glyphicon glyphicon-plus";
|
||||
$scope.visibleBk = false;
|
||||
$scope.imgBkUrl = "glyphicon glyphicon-plus";
|
||||
$scope.predicate = '';
|
||||
$scope.reverse = true;
|
||||
$scope.order = function(predicate) {
|
||||
@@ -443,6 +513,15 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
|
||||
bridgeService.editDevice(device);
|
||||
$location.path('/editdevice');
|
||||
};
|
||||
$scope.backupDeviceDb = function (optionalbackupname) {
|
||||
bridgeService.backupDeviceDb(optionalbackupname);
|
||||
};
|
||||
$scope.restoreBackup = function (backupname) {
|
||||
bridgeService.restoreBackup(backupname);
|
||||
};
|
||||
$scope.deleteBackup = function (backupname) {
|
||||
bridgeService.deleteBackup(backupname);
|
||||
};
|
||||
$scope.toggle = function () {
|
||||
$scope.visible = !$scope.visible;
|
||||
if($scope.visible)
|
||||
@@ -450,6 +529,13 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
|
||||
else
|
||||
$scope.imgUrl = "glyphicon glyphicon-plus";
|
||||
};
|
||||
$scope.toggleBk = function () {
|
||||
$scope.visibleBk = !$scope.visibleBk;
|
||||
if($scope.visibleBk)
|
||||
$scope.imgBkUrl = "glyphicon glyphicon-minus";
|
||||
else
|
||||
$scope.imgBkUrl = "glyphicon glyphicon-plus";
|
||||
};
|
||||
});
|
||||
|
||||
app.controller('AddingController', function ($scope, $location, $http, bridgeService, BridgeSettings) {
|
||||
|
||||
@@ -134,3 +134,40 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default backup">
|
||||
<div class="panel-heading">
|
||||
<h1 class="panel-title">Bridge Device DB Backup <a ng-click="toggleBk()"><span class={{imgBkUrl}} aria-hidden="true"></a></h1>
|
||||
</div>
|
||||
<div ng-if="visibleBk" class="animate-if" class="panel-body">
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-xs-12 col-sm-2 control-label" for="backup-name">Backup File Name</label>
|
||||
|
||||
<div class="col-xs-8 col-sm-7">
|
||||
<input id="backup-name" class="form-control" type="text"
|
||||
ng-model="optionalbackupname" placeholder="Optional">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary"
|
||||
ng-click="backupDeviceDb(optionalbackupname)">Backup Device DB</button>
|
||||
</div>
|
||||
</form>
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Filename</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="backup in bridge.backups">
|
||||
<td>{{backup}}</td>
|
||||
<td>
|
||||
<button class="btn btn-danger" type="submit"
|
||||
ng-click="restoreBackup(backup)">Restore</button>
|
||||
<button class="btn btn-warning" type="submit"
|
||||
ng-click="deleteBackup(backup)">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user