List available cameras on web dashboard (#63)

- Available cameras can be added with a specific path
- Individual cameras show connection status
- Individual cameras show a list of alternate paths
This commit is contained in:
Peter Johnson
2019-01-13 15:44:59 -08:00
committed by GitHub
parent b0ecb03407
commit 4d2e328b12
7 changed files with 223 additions and 11 deletions
+82 -2
View File
@@ -40,8 +40,8 @@ function displayStatus(message) {
}
// Enable and disable buttons based on connection status
var connectedButtonIds = ['systemRestart', 'networkApproach', 'networkAddress', 'networkMask', 'networkGateway', 'networkDNS', 'visionUp', 'visionDown', 'visionTerm', 'visionKill', 'systemReadOnly', 'systemWritable', 'visionClient', 'visionTeam', 'visionDiscard', 'addCamera', 'applicationType'];
var connectedButtonClasses = ['cameraName', 'cameraPath', 'cameraPixelFormat', 'cameraWidth', 'cameraHeight', 'cameraFps', 'cameraBrightness', 'cameraWhiteBalance', 'cameraExposure', 'cameraProperties', 'cameraRemove', 'cameraCopyConfig']
var connectedButtonIds = ['systemRestart', 'networkApproach', 'networkAddress', 'networkMask', 'networkGateway', 'networkDNS', 'visionUp', 'visionDown', 'visionTerm', 'visionKill', 'systemReadOnly', 'systemWritable', 'visionClient', 'visionTeam', 'visionDiscard', 'addConnectedCamera', 'addCamera', 'applicationType'];
var connectedButtonClasses = ['cameraName', 'cameraPath', 'cameraAlternatePaths', 'cameraPixelFormat', 'cameraWidth', 'cameraHeight', 'cameraFps', 'cameraBrightness', 'cameraWhiteBalance', 'cameraExposure', 'cameraProperties', 'cameraRemove', 'cameraCopyConfig']
var writableButtonIds = ['networkSave', 'visionSave', 'applicationSave'];
var systemStatusIds = ['systemMemoryFree1s', 'systemMemoryFree5s',
'systemMemoryAvail1s', 'systemMemoryAvail5s',
@@ -54,6 +54,7 @@ function displayDisconnected() {
displayReadOnly();
$('#connectionBadge').removeClass('badge-primary').addClass('badge-secondary').text('Disconnected');
$('#visionServiceStatus').removeClass('badge-primary').removeClass('badge-secondary').addClass('badge-dark').text('Unknown Status');
$('.cameraConnectionBadge').removeClass('badge-primary').removeClass('badge-secondary').addClass('badge-dark').text('Unknown Status');
for (var i = 0; i < connectedButtonIds.length; i++) {
$('#' + connectedButtonIds[i]).prop('disabled', true);
}
@@ -114,6 +115,7 @@ $('#systemWritable').click(function() {
// Vision settings
var visionSettingsServer = {};
var visionSettingsDisplay = {'cameras': []};
var cameraList = [];
function pushVisionLogEnabled() {
var msg = {
@@ -204,6 +206,10 @@ function connect() {
case 'status':
displayStatus(msg.message);
break;
case 'cameraList':
cameraList = msg.cameras;
updateCameraListView();
break;
}
};
}
@@ -425,6 +431,7 @@ function appendNewVisionCameraView(value, i) {
camera.find('.cameraRemove').click(function() {
visionSettingsDisplay.cameras.splice(i, 1);
camera.remove();
updateCameraListView();
});
camera.find('.cameraSettingsFile').change(function() {
if (this.files.length <= 0) {
@@ -459,6 +466,9 @@ function appendNewVisionCameraView(value, i) {
camera.find('[data-target]').each(function() {
$(this).attr('data-target', $(this).attr('data-target').replace('NEW', i));
});
camera.find('[aria-labelledby]').each(function() {
$(this).attr('aria-labelledby', $(this).attr('aria-labelledby').replace('NEW', i));
});
$('#cameras').append(camera);
}
@@ -477,6 +487,7 @@ function updateVisionSettingsView() {
visionSettingsDisplay.cameras.forEach(function (value, i) {
appendNewVisionCameraView(value, i);
});
updateCameraListView();
feather.replace();
}
@@ -554,8 +565,77 @@ $('#addCamera').click(function() {
var i = visionSettingsDisplay.cameras.length;
visionSettingsDisplay.cameras.push({});
appendNewVisionCameraView({}, i);
updateCameraListView();
});
function updateCameraListView() {
var addConnectedDropdown = $('#addConnectedCameraList');
addConnectedDropdown.html('');
// disable all the alternate paths by default
visionSettingsDisplay.cameras.forEach(function (value, k) {
var cameraElem = $('#camera' + k);
cameraElem.find('.cameraConnectionBadge').removeClass('badge-dark').removeClass('badge-primary').addClass('badge-secondary').text('Disconnected');
cameraElem.find('.cameraAlternatePathsList').html('');
cameraElem.find('.cameraAlternatePaths').prop('disabled', true);
});
cameraList.forEach(function (camera, i) {
// See if one of the paths is an already existing camera
// Include the "main path" as the first path
var matchedCamera = false;
var paths = [camera.path];
camera.otherPaths.forEach(function (path, j) {
paths.push(path);
});
paths.forEach(function (path, j) {
visionSettingsDisplay.cameras.forEach(function (value, k) {
var cameraElem = $('#camera' + k);
var pathElem = cameraElem.find('.cameraPath');
if (path === pathElem.val()) {
matchedCamera = true;
// show camera as connected
cameraElem.find('.cameraConnectionBadge').removeClass('badge-dark').removeClass('badge-secondary').addClass('badge-primary').text('Connected');
// build alternate path list
var setAlternateDropdown = cameraElem.find('.cameraAlternatePathsList');
setAlternateDropdown.html('');
paths.forEach(function (altPath, j) {
setAlternateDropdown.append('<button class="dropdown-item cameraSetAlternatePath" type="button">' + altPath + '</button>');
});
cameraElem.find('.cameraAlternatePaths').prop('disabled', setAlternateDropdown.html() === '');
// hook up dropdown items to set alternate path
setAlternateDropdown.find('.cameraSetAlternatePath').click(function() {
pathElem.val($(this).text());
});
}
});
});
if (!matchedCamera) {
// add it to add connected camera list
addConnectedDropdown.append('<h5 class="dropdown-header">' + camera.name + '</h5>');
paths.forEach(function (path, j) {
addConnectedDropdown.append('<button class="dropdown-item addConnectedCameraItem" type="button">' + path + '</button>');
});
}
});
$('#addConnectedCamera').prop('disabled', addConnectedDropdown.html() === '');
// hook up dropdown items to create cameras
addConnectedDropdown.find('.addConnectedCameraItem').click(function() {
var i = visionSettingsDisplay.cameras.length;
var camera = {"path": $(this).text()};
visionSettingsDisplay.cameras.push(camera);
appendNewVisionCameraView(camera, i);
updateCameraListView();
});
}
var applicationFiles = [];
// Show details when appropriate for application type
+24 -4
View File
@@ -244,6 +244,7 @@
<button class="btn btn-link" type="button" data-toggle="collapse" data-target="#cameraBodyNEW">
<h6 class="cameraTitle">Camera NEW</h6>
</button>
<span class="badge badge-secondary align-text-top cameraConnectionBadge">Disconnected</span>
</div>
<div class="col-auto">
<a class="btn btn-sm btn-success cameraStream" href="" target="_blank" role="button">
@@ -261,13 +262,22 @@
<div class="card-body">
<form>
<div class="form-row">
<div class="form-group col">
<div class="form-group col col-4">
<label for="cameraNameNEW">Name</label>
<input type="text" class="form-control cameraName" id="cameraNameNEW">
</div>
<div class="form-group col">
<label for="cameraPathNEW">Path</label>
<input type="text" class="form-control cameraPath" id="cameraPathNEW">
<div class="input-group">
<input type="text" class="form-control cameraPath" id="cameraPathNEW">
<div class="input-group-append">
<button type="button" class="btn dropdown-toggle cameraAlternatePaths" id="cameraAlternatePathsNEW" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" disabled="true">
Alternate Path
</button>
<div class="dropdown-menu cameraAlternatePathsList" aria-labelledby="cameraAlternatePathsNEW">
</div>
</div>
</div>
</div>
</div>
<div class="form-group">
@@ -336,15 +346,25 @@
<span data-feather="save"></span>
Save
</button>
<button type="button" class="btn btn-secondary" id="visionDiscard">
<button type="button" class="btn btn-warning" id="visionDiscard">
<span data-feather="x"></span>
Discard Changes
</button>
</div>
<div class="col-auto">
<div class="dropdown">
<button type="button" class="btn btn-info dropdown-toggle" id="addConnectedCamera" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" disabled="true">
<span data-feather="plus"></span>
Add Connected Camera
</button>
<div class="dropdown-menu" aria-labelledby="addConnectedCamera" id="addConnectedCameraList">
</div>
</div>
</div>
<div class="col-auto">
<button type="button" class="btn btn-success" id="addCamera">
<span data-feather="plus"></span>
Add Camera
Add Other Camera
</button>
</div>
</div>