Implement vision settings and start adding app settings
This commit is contained in:
+204
-27
@@ -3,20 +3,19 @@ var connection = null;
|
||||
|
||||
var WebSocket = WebSocket || MozWebSocket;
|
||||
|
||||
/*
|
||||
// Implement bootstrap 3 style button loading support
|
||||
(function($) {
|
||||
$.fn.button = function(action) {
|
||||
if (action === 'loading' && this.data('loading-text')) {
|
||||
this.data('original-text', this.html()).html(this.data('loading-text')).prop('disabled', true);
|
||||
feather.replace();
|
||||
}
|
||||
if (action === 'reset' && this.data('original-text')) {
|
||||
this.html(this.data('original-text')).prop('disabled', false);
|
||||
feather.replace();
|
||||
}
|
||||
feather.replace();
|
||||
};
|
||||
}(jQuery));
|
||||
*/
|
||||
|
||||
// HTML escaping
|
||||
var entityMap = {
|
||||
@@ -41,8 +40,9 @@ function displayStatus(message) {
|
||||
}
|
||||
|
||||
// Enable and disable buttons based on connection status
|
||||
var connectedButtonIds = ['systemRestart', 'networkApproach', 'visionUp', 'visionDown', 'visionTerm', 'visionKill', 'systemReadOnly', 'systemWritable'];
|
||||
var writableButtonIds = ['networkSave'];
|
||||
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']
|
||||
var writableButtonIds = ['networkSave', 'visionSave', 'applicationSave'];
|
||||
var systemStatusIds = ['systemMemoryFree1s', 'systemMemoryFree5s',
|
||||
'systemMemoryAvail1s', 'systemMemoryAvail5s',
|
||||
'systemCpuUser1s', 'systemCpuUser5s',
|
||||
@@ -57,6 +57,9 @@ function displayDisconnected() {
|
||||
for (var i = 0; i < connectedButtonIds.length; i++) {
|
||||
$('#' + connectedButtonIds[i]).prop('disabled', true);
|
||||
}
|
||||
for (var i = 0; i < connectedButtonClasses.length; i++) {
|
||||
$('.' + connectedButtonClasses[i]).prop('disabled', true);
|
||||
}
|
||||
for (var i = 0; i < systemStatusIds.length; i++) {
|
||||
$('#' + systemStatusIds[i]).text("");
|
||||
}
|
||||
@@ -67,6 +70,9 @@ function displayConnected() {
|
||||
for (var i = 0; i < connectedButtonIds.length; i++) {
|
||||
$('#' + connectedButtonIds[i]).prop('disabled', false);
|
||||
}
|
||||
for (var i = 0; i < connectedButtonClasses.length; i++) {
|
||||
$('.' + connectedButtonClasses[i]).prop('disabled', false);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable and disable buttons based on writable status
|
||||
@@ -105,6 +111,10 @@ $('#systemWritable').click(function() {
|
||||
connection.send(JSON.stringify(msg));
|
||||
});
|
||||
|
||||
// Vision settings
|
||||
var visionSettingsServer = {};
|
||||
var visionSettingsDisplay = {'cameras': []};
|
||||
|
||||
// WebSocket automatic reconnection timer
|
||||
var reconnectTimerId = 0;
|
||||
|
||||
@@ -132,6 +142,9 @@ function connect() {
|
||||
// WebSocket incoming message handling
|
||||
connection.onmessage = function(evt) {
|
||||
var msg = JSON.parse(evt.data);
|
||||
if (msg === null) {
|
||||
return;
|
||||
}
|
||||
switch (msg.type) {
|
||||
case 'systemStatus':
|
||||
for (var i = 0; i < systemStatusIds.length; i++) {
|
||||
@@ -160,6 +173,19 @@ function connect() {
|
||||
$('#networkDNS').val(msg.networkDNS);
|
||||
updateNetworkSettingsView();
|
||||
break;
|
||||
case 'visionSettings':
|
||||
visionSettingsServer = msg.settings;
|
||||
visionSettingsDisplay = $.extend(true, {}, visionSettingsServer);
|
||||
updateVisionSettingsView();
|
||||
break;
|
||||
case 'applicationSettings':
|
||||
$('#applicationType').val(msg.applicationType);
|
||||
updateApplicationView();
|
||||
break;
|
||||
case 'applicationSaveComplete':
|
||||
$('#applicationSave').button('reset');
|
||||
updateApplicationView();
|
||||
break;
|
||||
case 'systemReadOnly':
|
||||
displayReadOnly();
|
||||
break;
|
||||
@@ -303,47 +329,198 @@ $('#visionClient').change(function() {
|
||||
}
|
||||
});
|
||||
|
||||
// Update view from data structure
|
||||
var visionSettings = {
|
||||
team: '294',
|
||||
ntmode: 'client',
|
||||
cameras: []
|
||||
};
|
||||
function updateVisionCameraView(camera, value) {
|
||||
if ('name' in value) {
|
||||
camera.find('.cameraTitle').text('Camera ' + value.name);
|
||||
camera.find('.cameraName').val(value.name);
|
||||
}
|
||||
if ('path' in value) {
|
||||
camera.find('.cameraPath').val(value.path);
|
||||
}
|
||||
camera.find('.cameraPixelFormat').val(value['pixel format']);
|
||||
camera.find('.cameraWidth').val(value.width);
|
||||
camera.find('.cameraHeight').val(value.height);
|
||||
camera.find('.cameraFps').val(value.fps);
|
||||
camera.find('.cameraBrightness').val(value.brightness);
|
||||
camera.find('.cameraWhiteBalance').val(value['white balance']);
|
||||
camera.find('.cameraExposure').val(value.exposure);
|
||||
camera.find('.cameraProperties').val(JSON.stringify(value.properties));
|
||||
}
|
||||
|
||||
function updateVisionSettingsCameraView(cardElem, data) {
|
||||
function appendNewVisionCameraView(value, i) {
|
||||
var camera = $('#cameraNEW').clone();
|
||||
camera.attr('id', 'camera' + i);
|
||||
camera.addClass('cameraSetting');
|
||||
camera.removeAttr('style');
|
||||
|
||||
updateVisionCameraView(camera, value);
|
||||
camera.find('.cameraStream').attr('href', 'http://' + window.location.hostname + ':' + (1181 + i) + '/');
|
||||
camera.find('.cameraRemove').click(function() {
|
||||
visionSettingsDisplay.cameras.splice(i, 1);
|
||||
camera.remove();
|
||||
});
|
||||
camera.find('.cameraSettingsFile').change(function() {
|
||||
if (this.files.length <= 0) {
|
||||
return false;
|
||||
}
|
||||
var fr = new FileReader();
|
||||
fr.onload = function(e) {
|
||||
var result = JSON.parse(e.target.result);
|
||||
if (!('name' in result)) {
|
||||
result.name = visionSettingsDisplay.cameras[i].name;
|
||||
}
|
||||
if (!('path' in result)) {
|
||||
result.path = visionSettingsDisplay.cameras[i].path;
|
||||
}
|
||||
visionSettingsDisplay.cameras[i] = result;
|
||||
updateVisionCameraView(camera, result);
|
||||
};
|
||||
fr.readAsText(this.files.item(0));
|
||||
});
|
||||
|
||||
camera.find('[id]').each(function() {
|
||||
$(this).attr('id', $(this).attr('id').replace('NEW', i));
|
||||
});
|
||||
camera.find('[for]').each(function() {
|
||||
$(this).attr('for', $(this).attr('for').replace('NEW', i));
|
||||
});
|
||||
camera.find('[data-target]').each(function() {
|
||||
$(this).attr('data-target', $(this).attr('data-target').replace('NEW', i));
|
||||
});
|
||||
|
||||
$('#cameras').append(camera);
|
||||
}
|
||||
|
||||
function updateVisionSettingsView() {
|
||||
$('#visionClient').prop('checked', visionSettings.ntmode === 'client');
|
||||
if (visionSettings.ntmode === 'client') {
|
||||
var isClient = !visionSettingsDisplay.ntmode || visionSettingsDisplay.ntmode === 'client';
|
||||
$('#visionClient').prop('checked', isClient);
|
||||
if (isClient) {
|
||||
$('#visionClientDetails').collapse('show');
|
||||
} else {
|
||||
$('#visionClientDetails').collapse('hide');
|
||||
}
|
||||
$('#visionTeam').val(visionSettings.team);
|
||||
$('#visionTeam').val(visionSettingsDisplay.team);
|
||||
|
||||
var newCamera = $('#cameraNEW').clone();
|
||||
newCamera.find('[id]').each(function() {
|
||||
$(this).attr('id', $(this).attr('id').replace('NEW', ''));
|
||||
});
|
||||
newCamera.find('[for]').each(function() {
|
||||
$(this).attr('for', $(this).attr('for').replace('NEW', ''));
|
||||
$('.cameraSetting').remove();
|
||||
visionSettingsDisplay.cameras.forEach(function (value, i) {
|
||||
appendNewVisionCameraView(value, i);
|
||||
});
|
||||
feather.replace();
|
||||
}
|
||||
|
||||
$('#cameraSettingsFile0').change(function() {
|
||||
if (this.files.length <= 0) {
|
||||
return false;
|
||||
$('#visionSave').click(function() {
|
||||
// update json from view
|
||||
visionSettingsDisplay.ntmode = $('#visionClient').prop('checked') ? 'client' : 'server';
|
||||
visionSettingsDisplay.team = parseInt($('#visionTeam').val(), 10);
|
||||
visionSettingsDisplay.cameras.forEach(function (value, i) {
|
||||
var camera = $('#camera' + i);
|
||||
value.name = camera.find('.cameraName').val();
|
||||
value.path = camera.find('.cameraPath').val();
|
||||
value['pixel format'] = camera.find('.cameraPixelFormat').val();
|
||||
value.width = parseInt(camera.find('.cameraWidth').val(), 10);
|
||||
if (isNaN(value.width)) {
|
||||
delete value["width"];
|
||||
}
|
||||
value.height = parseInt(camera.find('.cameraHeight').val(), 10);
|
||||
if (isNaN(value.height)) {
|
||||
delete value["height"];
|
||||
}
|
||||
value.fps = parseInt(camera.find('.cameraFps').val(), 10);
|
||||
if (isNaN(value.fps)) {
|
||||
delete value["fps"];
|
||||
}
|
||||
|
||||
var brightness = camera.find('.cameraBrightness').val();
|
||||
if (brightness !== '') {
|
||||
value.brightness = parseInt(brightness);
|
||||
if (isNaN(value.brightness)) {
|
||||
value.brightness = brightness;
|
||||
}
|
||||
} else {
|
||||
delete value['brightness'];
|
||||
}
|
||||
|
||||
var whiteBalance = camera.find('.cameraWhiteBalance').val();
|
||||
if (whiteBalance !== '') {
|
||||
value['white balance'] = parseInt(whiteBalance);
|
||||
if (isNaN(value['white balance'])) {
|
||||
value['white balance'] = whiteBalance;
|
||||
}
|
||||
} else {
|
||||
delete value['white balance'];
|
||||
}
|
||||
|
||||
var exposure = camera.find('.cameraExposure').val();
|
||||
if (exposure !== '') {
|
||||
value.exposure = parseInt(exposure);
|
||||
if (isNaN(value.exposure)) {
|
||||
value.exposure = exposure;
|
||||
}
|
||||
} else {
|
||||
delete value['exposure'];
|
||||
}
|
||||
|
||||
try {
|
||||
value.properties = JSON.parse(camera.find('.cameraProperties').val());
|
||||
} catch (err) {
|
||||
delete value['properties'];
|
||||
}
|
||||
});
|
||||
var msg = {
|
||||
type: 'visionSave',
|
||||
settings: visionSettingsDisplay
|
||||
};
|
||||
connection.send(JSON.stringify(msg));
|
||||
});
|
||||
|
||||
$('#visionDiscard').click(function() {
|
||||
visionSettingsDisplay = $.extend(true, {}, visionSettingsServer);
|
||||
updateVisionSettingsView();
|
||||
});
|
||||
|
||||
$('#addCamera').click(function() {
|
||||
var i = visionSettingsDisplay.cameras.length;
|
||||
visionSettingsDisplay.cameras.push({});
|
||||
appendNewVisionCameraView({}, i);
|
||||
});
|
||||
|
||||
// Show details when appropriate for application type
|
||||
function updateApplicationView() {
|
||||
if ($('#applicationType').val().startsWith("upload")) {
|
||||
$('#applicationUpload').collapse('show');
|
||||
} else {
|
||||
$('#applicationUpload').collapse('hide');
|
||||
}
|
||||
$('#applicationFile').val(null);
|
||||
}
|
||||
|
||||
$('#applicationType').change(function() {
|
||||
updateApplicationView();
|
||||
});
|
||||
|
||||
$('#applicationSave').click(function() {
|
||||
var msg = {
|
||||
type: 'applicationSave',
|
||||
applicationType: $('#applicationType').val()
|
||||
};
|
||||
connection.send(JSON.stringify(msg));
|
||||
|
||||
// upload the file if requested
|
||||
var f = $('#applicationFile');
|
||||
if (f.files.length <= 0) {
|
||||
return;
|
||||
}
|
||||
$('#applicationSave').button('loading');
|
||||
var fr = new FileReader();
|
||||
fr.onload = function(e) {
|
||||
var result = JSON.parse(e.target.result);
|
||||
console.log(result);
|
||||
connection.send(e.target.result);
|
||||
};
|
||||
fr.readAsText(this.files.item(0));
|
||||
fr.readAsArrayBuffer(f.files.item(0));
|
||||
});
|
||||
|
||||
// Start with display disconnected and start initial connection attempt
|
||||
displayDisconnected();
|
||||
updateNetworkSettingsView();
|
||||
updateVisionSettingsView();
|
||||
updateApplicationView();
|
||||
connect();
|
||||
|
||||
+86
-102
@@ -56,6 +56,12 @@
|
||||
Vision Settings
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="application-tab" data-toggle="tab" href="#application">
|
||||
<i class="nav-icon" data-feather="cpu"></i>
|
||||
Application
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
@@ -208,7 +214,7 @@
|
||||
<div class="tab-pane" id="vision-settings" role="tabpanel" aria-labelledby="vision-settings-tab">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5>Network Tables</h5>
|
||||
<h6>Network Tables</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form>
|
||||
@@ -231,105 +237,20 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion" id="cameras">
|
||||
<div class="card" id="camera0">
|
||||
<div class="card-header">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto mr-auto">
|
||||
<button class="btn btn-link" type="button" data-toggle="collapse" data-target="#cameraBody0">
|
||||
<h5>Camera 1</h5>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<a class="btn btn-sm btn-success" href="" target="_blank" role="button" id="cameraStream0">
|
||||
<span data-feather="play"></span>
|
||||
Open Stream
|
||||
</a>
|
||||
<button type="button" class="btn btn-sm btn-danger" id="cameraRemove0">
|
||||
<span data-feather="x"></span>
|
||||
Remove
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse" id="cameraBody0" data-parent="#cameras">
|
||||
<div class="card-body">
|
||||
<form>
|
||||
<div class="form-row">
|
||||
<div class="form-group col">
|
||||
<label for="cameraName0">Name</label>
|
||||
<input type="text" class="form-control" id="cameraName0">
|
||||
</div>
|
||||
<div class="form-group col">
|
||||
<label for="cameraPath0">Path</label>
|
||||
<input type="text" class="form-control" id="cameraPath0">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="custom-file">
|
||||
<input type="file" class="custom-file-input" accept=".json,text/json,application/json" id="cameraSettingsFile0">
|
||||
<label class="custom-file-label" for="cameraSettingsFile0">Load camera settings from JSON file</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-auto">
|
||||
<label for="cameraPixelFormat0">Pixel Format</label>
|
||||
<select class="form-control" id="cameraPixelFormat0">
|
||||
<option value="mjpeg">MJPEG</option>
|
||||
<option value="yuyv">YUYV</option>
|
||||
<option value="rgb565">RGB565</option>
|
||||
<option value="bgr">BGR</option>
|
||||
<option value="gray">Gray</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-auto">
|
||||
<label for="cameraWidth0">Width</label>
|
||||
<input type="text" class="form-control" id="cameraWidth0" size="5">
|
||||
</div>
|
||||
<div class="form-group col-auto">
|
||||
<label for="cameraHeight0">Height</label>
|
||||
<input type="text" class="form-control" id="cameraHeight0" size="5">
|
||||
</div>
|
||||
<div class="form-group col-auto">
|
||||
<label for="cameraFps0">FPS</label>
|
||||
<input type="text" class="form-control" id="cameraFps0" size="4">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-auto">
|
||||
<label for="cameraBrightness0">Brightness</label>
|
||||
<input type="text" class="form-control" id="cameraBrightness0" size="4">
|
||||
</div>
|
||||
<div class="form-group col-auto">
|
||||
<label for="cameraBrightness0">White Balance</label>
|
||||
<input type="text" class="form-control" id="cameraWhiteBalance0" size="4">
|
||||
</div>
|
||||
<div class="form-group col-auto">
|
||||
<label for="cameraBrightness0">Exposure</label>
|
||||
<input type="text" class="form-control" id="cameraExposure0" size="4">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="cameraProperties0">Custom Properties JSON</label>
|
||||
<textarea class="form-control" id="cameraProperties0" rows="3"></textarea>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" style="display:none" id="cameraNEW">
|
||||
<div class="card-header">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto mr-auto">
|
||||
<button class="btn btn-link" type="button" data-toggle="collapse" data-target="#cameraBodyNEW">
|
||||
<h5>Camera NEW</h5>
|
||||
<h6 class="cameraTitle">Camera NEW</h6>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<a class="btn btn-sm btn-success" href="" target="_blank" role="button" id="cameraStreamNEW">
|
||||
<a class="btn btn-sm btn-success cameraStream" href="" target="_blank" role="button">
|
||||
<span data-feather="play"></span>
|
||||
Open Stream
|
||||
</a>
|
||||
<button type="button" class="btn btn-sm btn-danger" id="cameraRemoveNEW">
|
||||
<button type="button" class="btn btn-sm btn-danger cameraRemove">
|
||||
<span data-feather="x"></span>
|
||||
Remove
|
||||
</button>
|
||||
@@ -342,23 +263,23 @@
|
||||
<div class="form-row">
|
||||
<div class="form-group col">
|
||||
<label for="cameraNameNEW">Name</label>
|
||||
<input type="text" class="form-control" id="cameraNameNEW">
|
||||
<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" id="cameraPathNEW">
|
||||
<input type="text" class="form-control cameraPath" id="cameraPathNEW">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="custom-file">
|
||||
<input type="file" class="custom-file-input" accept=".json,text/json,application/json" id="cameraSettingsFileNEW">
|
||||
<label class="custom-file-label" for="cameraSettingsFileNEW">Load camera settings from JSON file</label>
|
||||
<input type="file" class="custom-file-input cameraSettingsFile" accept=".json,text/json,application/json" id="cameraSettingsFileNEW">
|
||||
<label class="custom-file-label" for="cameraSettingsFileNEW">Load source config from JSON file</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-auto">
|
||||
<label for="cameraPixelFormatNEW">Pixel Format</label>
|
||||
<select class="form-control" id="cameraPixelFormatNEW">
|
||||
<select class="form-control cameraPixelFormat" id="cameraPixelFormatNEW">
|
||||
<option value="mjpeg">MJPEG</option>
|
||||
<option value="yuyv">YUYV</option>
|
||||
<option value="rgb565">RGB565</option>
|
||||
@@ -368,34 +289,34 @@
|
||||
</div>
|
||||
<div class="form-group col-auto">
|
||||
<label for="cameraWidthNEW">Width</label>
|
||||
<input type="text" class="form-control" id="cameraWidthNEW" size="5">
|
||||
<input type="number" class="form-control cameraWidth" id="cameraWidthNEW" size="5">
|
||||
</div>
|
||||
<div class="form-group col-auto">
|
||||
<label for="cameraHeightNEW">Height</label>
|
||||
<input type="text" class="form-control" id="cameraHeightNEW" size="5">
|
||||
<input type="number" class="form-control cameraHeight" id="cameraHeightNEW" size="5">
|
||||
</div>
|
||||
<div class="form-group col-auto">
|
||||
<label for="cameraFpsNEW">FPS</label>
|
||||
<input type="text" class="form-control" id="cameraFpsNEW" size="4">
|
||||
<input type="number" class="form-control cameraFps" id="cameraFpsNEW" size="4">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-auto">
|
||||
<label for="cameraBrightnessNEW">Brightness</label>
|
||||
<input type="text" class="form-control" id="cameraBrightnessNEW" size="4">
|
||||
<input type="text" class="form-control cameraBrightness" id="cameraBrightnessNEW" size="4">
|
||||
</div>
|
||||
<div class="form-group col-auto">
|
||||
<label for="cameraBrightnessNEW">White Balance</label>
|
||||
<input type="text" class="form-control" id="cameraWhiteBalanceNEW" size="4">
|
||||
<label for="cameraWhiteBalanceNEW">White Balance</label>
|
||||
<input type="text" class="form-control cameraWhiteBalance" id="cameraWhiteBalanceNEW" size="4">
|
||||
</div>
|
||||
<div class="form-group col-auto">
|
||||
<label for="cameraExposureNEW">Exposure</label>
|
||||
<input type="text" class="form-control" id="cameraExposureNEW" size="4">
|
||||
<input type="text" class="form-control cameraExposure" id="cameraExposureNEW" size="4">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="cameraPropertiesNEW">Custom Properties JSON</label>
|
||||
<textarea class="form-control" id="cameraPropertiesNEW" rows="3"></textarea>
|
||||
<textarea class="form-control cameraProperties" id="cameraPropertiesNEW" rows="3"></textarea>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -423,6 +344,69 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Application -->
|
||||
<div class="tab-pane" id="application" role="tabpanel" aria-labelledby="application-tab">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h6>Vision Application Configuration</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="applicationType">Application</label>
|
||||
<select class="form-control" id="applicationType">
|
||||
<option value="builtin">Built-in multi-camera streaming</option>
|
||||
<option value="custom">Custom</option>
|
||||
<option value="example-java">Java example (must be built to work)</option>
|
||||
<option value="example-cpp">C++ example (must be built to work)</option>
|
||||
<option value="example-python">Python example</option>
|
||||
<option value="upload-java">Uploaded Java jar</option>
|
||||
<option value="upload-cpp">Uploaded C++ executable</option>
|
||||
<option value="upload-python">Uploaded Python file</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="collapse" id="applicationUpload">
|
||||
<div class="form-group">
|
||||
<label for="applicationFile">Upload executable file</label>
|
||||
<input type="file" class="form-control-file" id="applicationFile">
|
||||
</div>
|
||||
</div>
|
||||
<button id="applicationSave" type="button" class="btn btn-primary" data-loading-text="<i class='spin' data-feather='loader'></i> Saving" disabled>
|
||||
<span data-feather="save"></span>
|
||||
Save
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h6>Example Programs</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-auto">
|
||||
<a class="btn btn-sm btn-success" href="java-multiCameraServer.zip" target="_blank" role="button">
|
||||
<span data-feather="download"></span>
|
||||
Download Java Example
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<a class="btn btn-sm btn-success" href="cpp-multiCameraServer.zip" target="_blank" role="button">
|
||||
<span data-feather="download"></span>
|
||||
Download C++ Example
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<a class="btn btn-sm btn-success" href="python-multiCameraServer.zip" target="_blank" role="button">
|
||||
<span data-feather="download"></span>
|
||||
Download Python Example
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user