2018-12-04 08:50:29 +00:00
|
|
|
function uuidv4() {
|
|
|
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
|
|
|
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
|
|
|
|
return v.toString(16);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function api(method, params, callback) {
|
|
|
|
var request = new XMLHttpRequest()
|
|
|
|
request.addEventListener('load', function (event) {
|
|
|
|
var response
|
|
|
|
try {
|
|
|
|
response = JSON.parse(event.target.responseText)
|
|
|
|
} catch(e) {
|
|
|
|
response = {
|
|
|
|
error: {code: -32700, message: 'Parse error'}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
callback && callback(response)
|
|
|
|
}, false)
|
|
|
|
request.addEventListener('error', function (evt) {
|
|
|
|
callback && callback({error: {code: -32000, message: 'Server error'}})
|
|
|
|
}, false)
|
|
|
|
request.open('POST', '/api/')
|
|
|
|
request.setRequestHeader('Content-type', 'application/json')
|
|
|
|
request.send(JSON.stringify(
|
|
|
|
{method: method, params: params, jsonrpc: '2.0'}
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function requiredFieldValidator(value) {
|
|
|
|
if (value == null || value == undefined || !value.length) {
|
|
|
|
return {valid: false, msg: "This is a required field"};
|
|
|
|
} else {
|
|
|
|
return {valid: true, msg: null};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function isInt(value) {
|
|
|
|
return !isNaN(value) &&
|
|
|
|
parseInt(Number(value)) == value &&
|
|
|
|
!isNaN(parseInt(value, 10));
|
|
|
|
}
|
|
|
|
|
|
|
|
function integerValidator(value) {
|
|
|
|
if (value == null || value == undefined || !value.length || !isInt(value)) {
|
|
|
|
return {valid: false, msg: "Value must be a number"};
|
|
|
|
} else {
|
|
|
|
return {valid: true, msg: null};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-06 12:42:13 +00:00
|
|
|
var currentSequence;
|
2018-12-04 08:50:29 +00:00
|
|
|
var presets = [];
|
2020-12-05 11:55:59 +00:00
|
|
|
var system_presets = [
|
|
|
|
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
|
|
|
|
90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105
|
|
|
|
];
|
2018-12-04 08:50:29 +00:00
|
|
|
|
2020-12-05 11:55:59 +00:00
|
|
|
function presetSelect(all) {
|
2018-12-05 12:58:12 +00:00
|
|
|
var options = ''
|
2020-12-05 11:55:59 +00:00
|
|
|
if (all) {
|
|
|
|
for (var id=1;id<=300;id++) {
|
|
|
|
if (system_presets.indexOf(id) == -1) {
|
|
|
|
var preset = getPreset(id)
|
|
|
|
if (preset) {
|
|
|
|
options += '<option value="'+preset.id+'">' + preset.id + ': ' + preset.name + '</option>';
|
|
|
|
} else {
|
|
|
|
options += '<option value="'+id+'">' + id + ': Preset ' + id + '</option>';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
presets.forEach(function(preset) {
|
|
|
|
options += '<option value="'+preset.id+'">' + preset.id + ': ' + preset.name + '</option>';
|
|
|
|
})
|
|
|
|
}
|
2018-12-05 12:58:12 +00:00
|
|
|
return $('<select name="preset-editor">' + options + '</select>')
|
|
|
|
}
|
|
|
|
|
2018-12-04 08:50:29 +00:00
|
|
|
function PresetEditor(args) {
|
|
|
|
var $preset;
|
|
|
|
var scope = this;
|
|
|
|
|
|
|
|
this.init = function () {
|
2018-12-05 12:58:12 +00:00
|
|
|
$preset = presetSelect()
|
2018-12-04 08:50:29 +00:00
|
|
|
.appendTo(args.container);
|
|
|
|
scope.focus();
|
|
|
|
};
|
|
|
|
|
|
|
|
this.destroy = function () {
|
|
|
|
$(args.container).empty();
|
|
|
|
};
|
|
|
|
|
|
|
|
this.focus = function () {
|
|
|
|
$preset.focus();
|
|
|
|
};
|
|
|
|
|
|
|
|
this.serializeValue = function () {
|
|
|
|
return parseInt($preset.val(), 10);
|
|
|
|
};
|
|
|
|
|
|
|
|
this.applyValue = function (item, state) {
|
|
|
|
console.log('apply', item, state)
|
|
|
|
item.preset = state;
|
|
|
|
};
|
|
|
|
|
|
|
|
this.loadValue = function (item) {
|
|
|
|
$preset.val(item.preset);
|
|
|
|
};
|
|
|
|
|
|
|
|
this.isValueChanged = function () {
|
|
|
|
return args.item.preset != parseInt($preset.val(), 10);
|
|
|
|
};
|
|
|
|
|
|
|
|
this.validate = function () {
|
|
|
|
if (isNaN(parseInt($preset.val(), 10))) {
|
|
|
|
return {valid: false, msg: "Invalid preset."};
|
|
|
|
}
|
|
|
|
return {valid: true, msg: null};
|
|
|
|
};
|
|
|
|
|
|
|
|
this.init();
|
|
|
|
}
|
|
|
|
|
|
|
|
function PresetFormatter(row, cell, value, columnDef, dataContext) {
|
|
|
|
preset = presets.filter(function(preset) { return preset.id == value })[0];
|
|
|
|
if (preset) {
|
|
|
|
return preset.id + ': ' + preset.name;
|
|
|
|
} else {
|
|
|
|
return value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function formatNumber(number, decimals) {
|
|
|
|
var array = [],
|
|
|
|
abs = Math.abs(number),
|
|
|
|
split = abs.toFixed(decimals).split('.');
|
|
|
|
while (split[0]) {
|
|
|
|
array.unshift(split[0].slice(-3));
|
|
|
|
split[0] = split[0].slice(0, -3);
|
|
|
|
}
|
|
|
|
split[0] = array.join(',');
|
|
|
|
return (number < 0 ? '-' : '') + split.join('.');
|
|
|
|
};
|
|
|
|
|
|
|
|
function formatDuration(seconds) {
|
|
|
|
if (seconds == '...' || !seconds) {
|
|
|
|
return seconds
|
|
|
|
}
|
|
|
|
var values = [
|
|
|
|
Math.floor(seconds / 31536000),
|
|
|
|
Math.floor(seconds % 31536000 / 86400),
|
|
|
|
Math.floor(seconds % 86400 / 3600),
|
|
|
|
Math.floor(seconds % 3600 / 60),
|
|
|
|
formatNumber(seconds % 60, 3)
|
|
|
|
];
|
|
|
|
var labels = ['y', 'd', 'h', 'm', 's'];
|
|
|
|
var duration = '';
|
|
|
|
values.forEach(function(v, i) {
|
|
|
|
if (v) {
|
|
|
|
if (labels[i] == 's') {
|
|
|
|
v = v.replace('.', 's ').replace(' 000', '')
|
|
|
|
duration += v;
|
|
|
|
} else {
|
|
|
|
duration += v + labels[i] + ' ';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return duration
|
|
|
|
}
|
|
|
|
|
|
|
|
function formatTime(row, cell, value, columnDef, dataContext) {
|
|
|
|
var time = '';
|
|
|
|
if (row == 0) {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
if (data[row].duration) {
|
|
|
|
time = data.slice(0, row + 1).map(function(row) {
|
|
|
|
return row.duration || 0
|
|
|
|
}).reduce(function(a, b) { return a+b }, 0)
|
|
|
|
if (data[row].sleep) {
|
|
|
|
time -= data[row].sleep
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return formatDuration(time)
|
|
|
|
}
|
|
|
|
|
2018-12-05 13:07:11 +00:00
|
|
|
function formatShotTime(row, cell, value, columnDef, dataContext) {
|
|
|
|
if (data[row].duration) {
|
|
|
|
return formatDuration(data[row].duration)
|
|
|
|
}
|
|
|
|
return ''
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-12-04 08:50:29 +00:00
|
|
|
function CheckmarkFormatter(row, cell, value, columnDef, dataContext) {
|
|
|
|
return value ? "<img src='/static/sg/images/tick.png'>" : "";
|
|
|
|
}
|
|
|
|
|
|
|
|
function StatusFormatter(row, cell, value, columnDef, dataContext) {
|
|
|
|
return value ? "Next" : "";
|
|
|
|
}
|
|
|
|
|
|
|
|
var grid;
|
|
|
|
var data = [];
|
|
|
|
var nextStep;
|
|
|
|
var columns = [
|
|
|
|
{
|
|
|
|
id: "#",
|
|
|
|
name: "",
|
|
|
|
width: 10,
|
|
|
|
behavior: "selectAndMove",
|
|
|
|
selectable: false,
|
|
|
|
resizable: false,
|
|
|
|
cssClass: "cell-reorder dnd"
|
|
|
|
},
|
|
|
|
{id: "preset", name: "Preset", field: "preset", width: 180,
|
|
|
|
cssClass: "cell-title",
|
|
|
|
formatter: PresetFormatter,
|
|
|
|
editor: PresetEditor,
|
|
|
|
validator: requiredFieldValidator
|
|
|
|
},
|
|
|
|
{id: "speed", name: "Speed", field: "speed", editor: Slick.Editors.Integer, validator: integerValidator,
|
|
|
|
width: 60
|
|
|
|
},
|
|
|
|
{id: "sleep", name: "Sleep", field: "sleep", editor: Slick.Editors.Integer, validator: integerValidator,
|
|
|
|
width: 60
|
|
|
|
},
|
|
|
|
{id: "zoom", name: "Zoom Speed", field: "zoom", editor: Slick.Editors.Integer, validator: integerValidator, width: 75},
|
|
|
|
{id: "zoom_last", name: "Zoom Last", field: "zoom_last", cssClass: "cell-status", formatter: CheckmarkFormatter, editor: Slick.Editors.Checkbox, width: 60},
|
|
|
|
//{id: "duration", name: "Time", field: "duration", editor: Slick.Editors.Text, formatter: formatTime},
|
|
|
|
{id: "duration", name: "Time", field: "duration", formatter: formatTime},
|
2018-12-05 13:07:11 +00:00
|
|
|
{id: "shot_duration", name: "Duration", field: "shot_duration", formatter: formatShotTime},
|
2018-12-04 08:50:29 +00:00
|
|
|
{id: "status", name: "Status", width: 80, minWidth: 20, maxWidth: 80, cssClass: "cell-status", field: "status", formatter: StatusFormatter}
|
|
|
|
];
|
|
|
|
var options = {
|
|
|
|
editable: true,
|
|
|
|
enableAddRow: true,
|
|
|
|
enableCellNavigation: true,
|
|
|
|
asyncEditorLoading: false,
|
|
|
|
autoEdit: false
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function loadData(sequence) {
|
|
|
|
data = sequence;
|
|
|
|
grid = new Slick.Grid("#myGrid", data, columns, options);
|
|
|
|
|
|
|
|
grid.setSelectionModel(new Slick.CellSelectionModel());
|
|
|
|
var moveRowsPlugin = new Slick.RowMoveManager({
|
|
|
|
cancelEditOnDrag: true
|
|
|
|
});
|
|
|
|
moveRowsPlugin.onBeforeMoveRows.subscribe(function (e, data) {
|
|
|
|
for (var i = 0; i < data.rows.length; i++) {
|
|
|
|
// no point in moving before or after itself
|
|
|
|
if (data.rows[i] == data.insertBefore || data.rows[i] == data.insertBefore - 1) {
|
|
|
|
e.stopPropagation();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
|
|
|
|
moveRowsPlugin.onMoveRows.subscribe(function (e, args) {
|
|
|
|
var extractedRows = [], left, right;
|
|
|
|
var rows = args.rows;
|
|
|
|
var insertBefore = args.insertBefore;
|
|
|
|
left = data.slice(0, insertBefore);
|
|
|
|
right = data.slice(insertBefore, data.length);
|
|
|
|
|
|
|
|
rows.sort(function(a,b) { return a-b; });
|
|
|
|
|
|
|
|
for (var i = 0; i < rows.length; i++) {
|
|
|
|
extractedRows.push(data[rows[i]]);
|
|
|
|
}
|
|
|
|
|
|
|
|
rows.reverse();
|
|
|
|
|
|
|
|
for (var i = 0; i < rows.length; i++) {
|
|
|
|
var row = rows[i];
|
|
|
|
if (row < insertBefore) {
|
|
|
|
left.splice(row, 1);
|
|
|
|
} else {
|
|
|
|
right.splice(row - insertBefore, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
data = left.concat(extractedRows.concat(right));
|
|
|
|
|
|
|
|
var selectedRows = [];
|
|
|
|
for (var i = 0; i < rows.length; i++)
|
|
|
|
selectedRows.push(left.length + i);
|
|
|
|
|
|
|
|
grid.resetActiveCell();
|
|
|
|
grid.setData(data);
|
|
|
|
grid.setSelectedRows(selectedRows);
|
|
|
|
grid.render();
|
|
|
|
});
|
|
|
|
|
|
|
|
grid.registerPlugin(moveRowsPlugin);
|
|
|
|
|
|
|
|
grid.onAddNewRow.subscribe(function (e, args) {
|
|
|
|
var item = args.item;
|
|
|
|
item.speed = item.speed || data[data.length-1].speed
|
|
|
|
item.sleep = item.sleep || 0
|
|
|
|
grid.invalidateRow(data.length);
|
|
|
|
data.push(item);
|
|
|
|
grid.updateRowCount();
|
|
|
|
grid.render();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function totalDuration() {
|
|
|
|
return data.map(function(row) {
|
|
|
|
return row.duration || 0
|
|
|
|
}).reduce(function(a, b) { return a+b }, 0)
|
|
|
|
}
|
|
|
|
|
2021-10-20 08:31:42 +00:00
|
|
|
function formatDict(position) {
|
|
|
|
var pos = ''
|
|
|
|
Object.keys(position).forEach(key => {
|
|
|
|
var name = key
|
|
|
|
if (name == 'absoluteZoom') {
|
|
|
|
name = 'zoom'
|
|
|
|
}
|
|
|
|
pos += name + ': ' + position[key] + ' '
|
|
|
|
})
|
|
|
|
return pos.trim()
|
|
|
|
}
|
|
|
|
|
2018-12-04 08:50:29 +00:00
|
|
|
function updateStatus() {
|
|
|
|
api('status', {}, function(response) {
|
|
|
|
if (response.result) {
|
2020-12-06 12:42:13 +00:00
|
|
|
var gotSelection = grid.getSelectedRows().length > 0
|
|
|
|
var disabled = !gotSelection || response.result.status == 'Active'
|
|
|
|
|
2018-12-04 08:50:29 +00:00
|
|
|
$('#status').html(response.result.status)
|
2018-12-04 15:22:23 +00:00
|
|
|
$('button.run').attr({disabled: response.result.status == 'Active'})
|
2020-12-06 12:42:13 +00:00
|
|
|
$('button.run_from').attr({disabled: disabled})
|
2021-11-23 17:08:43 +00:00
|
|
|
$('button.loop').attr({disabled: disabled})
|
|
|
|
$('button.hour_loop').attr({disabled: disabled})
|
2020-12-06 12:42:13 +00:00
|
|
|
$('button.continue_from').attr({disabled: disabled})
|
2018-12-04 15:22:23 +00:00
|
|
|
$('button.stop').attr({disabled: response.result.status != 'Active'})
|
2018-12-04 08:50:29 +00:00
|
|
|
if (response.result.duration && response.result.status == 'Active') {
|
|
|
|
$('#duration').html(formatDuration(response.result.duration))
|
|
|
|
} else {
|
|
|
|
$('#duration').html(formatDuration(totalDuration()))
|
|
|
|
}
|
|
|
|
var update = false;
|
|
|
|
if (response.result.time) {
|
|
|
|
data.forEach(function(row) {
|
|
|
|
if (row.seqid in response.result.time && response.result.time[row.seqid] != row.duration) {
|
|
|
|
if (row.seqid == data[0].seqid || response.result.time[row.seqid]) {
|
|
|
|
console.log(row.duration, response.result.time[row.seqid]);
|
|
|
|
row.duration = response.result.time[row.seqid];
|
|
|
|
update = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
if (response.result.position) {
|
2021-10-20 08:31:42 +00:00
|
|
|
$('#position').html(formatDict(response.result.position))
|
2018-12-04 08:50:29 +00:00
|
|
|
}
|
|
|
|
data.forEach(function(row) {
|
|
|
|
var s = (response.result.next && row.seqid == response.result.next.seqid);
|
|
|
|
if (row.status != s) {
|
|
|
|
update = true
|
|
|
|
row.status = s
|
|
|
|
}
|
|
|
|
})
|
|
|
|
if (response.result.next) {
|
|
|
|
nextStep = response.result.next
|
|
|
|
if (response.result.next.seqid) {
|
|
|
|
delete response.result.next.seqid
|
|
|
|
}
|
|
|
|
if (response.result.next.duration) {
|
|
|
|
delete response.result.next.duration
|
|
|
|
}
|
2021-10-20 08:31:42 +00:00
|
|
|
$('#next').html('Next: ' + formatDict(response.result.next))
|
2018-12-04 08:50:29 +00:00
|
|
|
}
|
|
|
|
if (update) {
|
|
|
|
grid.invalidate();
|
|
|
|
grid.render();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
data.forEach(function(seq) {
|
|
|
|
if (!seq.seqid) {
|
|
|
|
seq.seqid = uuidv4()
|
|
|
|
}
|
|
|
|
})
|
2020-12-06 12:42:13 +00:00
|
|
|
var sequence = JSON.stringify(data.map(step => {
|
|
|
|
step = Object.assign({}, step)
|
|
|
|
delete step.duration
|
|
|
|
delete step.status
|
|
|
|
return step
|
|
|
|
}))
|
2020-12-06 16:27:38 +00:00
|
|
|
if (!currentSequence) {
|
|
|
|
currentSequence = sequence
|
|
|
|
}
|
2020-12-06 12:42:13 +00:00
|
|
|
if (sequence != currentSequence) {
|
|
|
|
console.log('updateSequence')
|
|
|
|
currentSequence = sequence
|
|
|
|
api('updateSequence', {sequence: data}, function() {})
|
|
|
|
}
|
2018-12-04 08:50:29 +00:00
|
|
|
|
|
|
|
var gotSelection = grid.getSelectedRows().length > 0
|
|
|
|
$('button.goto').attr({disabled: !gotSelection})
|
|
|
|
$('button.run_from').attr({disabled: !gotSelection})
|
|
|
|
$('button.continue_from').attr({disabled: !gotSelection})
|
|
|
|
$('button.insert').attr({disabled: !gotSelection})
|
|
|
|
$('button.delete').attr({disabled: !gotSelection})
|
|
|
|
}
|
|
|
|
|
2018-12-05 12:58:12 +00:00
|
|
|
|
|
|
|
var preset_offset = {}, current_position = {};
|
|
|
|
|
|
|
|
function updateShiftStatus() {
|
|
|
|
api('camera', {
|
|
|
|
'status': {}
|
|
|
|
}, function(response) {
|
|
|
|
if (response.result) {
|
|
|
|
if (response.result.status) {
|
|
|
|
current_position = response.result.status;
|
2018-12-05 13:16:30 +00:00
|
|
|
var preset = presets.filter(function(p) {
|
|
|
|
return p.id == parseInt($('select[name=preset-editor]').val(), 10)
|
|
|
|
})[0];
|
2018-12-05 12:58:12 +00:00
|
|
|
preset_offset['azimuth'] = preset['position']['azimuth'] - current_position['azimuth'];
|
|
|
|
preset_offset['elevation'] = preset['position']['elevation'] - current_position['elevation'];
|
|
|
|
preset_offset['absoluteZoom'] = preset['position']['absoluteZoom'] - current_position['absoluteZoom'];
|
|
|
|
updateDelta()
|
|
|
|
}
|
|
|
|
}
|
2018-12-04 08:50:29 +00:00
|
|
|
})
|
2018-12-05 12:58:12 +00:00
|
|
|
}
|
|
|
|
function updateDelta() {
|
|
|
|
$('#delta').html(JSON.stringify(preset_offset, null, ' '))
|
|
|
|
}
|
2018-12-04 08:50:29 +00:00
|
|
|
|
|
|
|
function deleteRows() {
|
|
|
|
var result = confirm("Are you sure you want to delete " + grid.getSelectedRows().length + " row(s)?");
|
|
|
|
if (result) {
|
|
|
|
var rowsToDelete = grid.getSelectedRows().sort().reverse();
|
|
|
|
for (var i = 0; i < rowsToDelete.length; i++) {
|
|
|
|
data.splice(rowsToDelete[i], 1);
|
|
|
|
}
|
|
|
|
grid.invalidate();
|
|
|
|
grid.setSelectedRows([]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$('button.goto').on({click: function() {
|
|
|
|
var selected = grid.getSelectedRows()[0];
|
|
|
|
api('camera', {
|
|
|
|
'fast_preset': {id: data[selected].preset}
|
|
|
|
}, function(response) {
|
|
|
|
//console.log(response)
|
|
|
|
})
|
|
|
|
}})
|
|
|
|
$('button.run').on({click: function() {
|
|
|
|
data.forEach(function(seq) {
|
|
|
|
if (!seq.seqid) {
|
|
|
|
seq.seqid = uuidv4()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
api('run', {
|
|
|
|
'steps': data
|
|
|
|
}, function(response) {
|
|
|
|
//console.log(response)
|
|
|
|
})
|
|
|
|
}})
|
2021-09-13 09:23:43 +00:00
|
|
|
$('button.loop').on({click: function() {
|
|
|
|
data.forEach(function(seq) {
|
|
|
|
if (!seq.seqid) {
|
|
|
|
seq.seqid = uuidv4()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
api('run', {
|
|
|
|
'steps': data,
|
|
|
|
'loop': true
|
|
|
|
}, function(response) {
|
|
|
|
//console.log(response)
|
|
|
|
})
|
|
|
|
}})
|
2021-11-23 09:44:28 +00:00
|
|
|
$('button.hour_loop').on({click: function() {
|
|
|
|
data.forEach(function(seq) {
|
|
|
|
if (!seq.seqid) {
|
|
|
|
seq.seqid = uuidv4()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
api('run', {
|
|
|
|
'steps': data,
|
|
|
|
'hour_loop': true
|
|
|
|
}, function(response) {
|
|
|
|
//console.log(response)
|
|
|
|
})
|
|
|
|
}})
|
2018-12-04 08:50:29 +00:00
|
|
|
$('button.run_from').on({click: function() {
|
|
|
|
var selected = grid.getSelectedRows()[0];
|
|
|
|
api('run', {
|
|
|
|
'steps': data.slice(selected)
|
|
|
|
}, function(response) {
|
|
|
|
//console.log(response)
|
|
|
|
})
|
|
|
|
}})
|
|
|
|
$('button.continue_from').on({click: function() {
|
|
|
|
var selected = grid.getSelectedRows()[0];
|
|
|
|
api('run', {
|
|
|
|
'steps': data.slice(selected),
|
|
|
|
'goto_first': false
|
|
|
|
}, function(response) {
|
|
|
|
console.log(response)
|
|
|
|
})
|
|
|
|
}})
|
|
|
|
$('button.stop').on({click: function() {
|
|
|
|
api('stop', {}, function(response) {
|
|
|
|
if (nextStep && grid.getSelectedRows().length == 0) {
|
|
|
|
var selected = data.map(function(row) { return row.preset }).indexOf(nextStep.preset)
|
|
|
|
grid.setSelectedRows([selected]);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}})
|
|
|
|
$('button.delete').on({click: deleteRows})
|
|
|
|
$('button.insert').on({click: function() {
|
|
|
|
var selected = grid.getSelectedRows()[0];
|
|
|
|
data.splice(selected, 0, {
|
|
|
|
preset: data[selected].preset,
|
|
|
|
speed: data[selected].speed,
|
|
|
|
seqid: uuidv4()
|
|
|
|
});
|
|
|
|
grid.invalidate();
|
|
|
|
grid.setSelectedRows([selected+1]);
|
|
|
|
}})
|
|
|
|
$('button.set_speed').on({click: function() {
|
|
|
|
var speed = parseInt($('input.default_speed').val(), 10)
|
|
|
|
data.forEach(function(row) {
|
|
|
|
row.speed = speed
|
|
|
|
})
|
|
|
|
grid.invalidate()
|
|
|
|
|
|
|
|
}})
|
|
|
|
|
2018-12-05 16:31:25 +00:00
|
|
|
function textBlob(data, type) {
|
|
|
|
type = type || 'text/plain; charset=utf-8';
|
2018-12-04 08:50:29 +00:00
|
|
|
var byteNumbers = new Array(data.length);
|
|
|
|
for (var i = 0; i < data.length; i++) {
|
|
|
|
byteNumbers[i] = data.charCodeAt(i);
|
|
|
|
}
|
|
|
|
var byteArray = new Uint8Array(byteNumbers);
|
2018-12-05 16:31:25 +00:00
|
|
|
var blob = new Blob([byteArray], {type: type});
|
2018-12-04 08:50:29 +00:00
|
|
|
return blob;
|
|
|
|
}
|
|
|
|
|
|
|
|
function exportSequence() {
|
|
|
|
return data.map(function(row) {
|
|
|
|
var r = {};
|
|
|
|
Object.keys(row).forEach(function(key) {
|
|
|
|
if (['status'].indexOf(key) == -1) {
|
|
|
|
r[key] = row[key];
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return r
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2018-12-05 16:18:57 +00:00
|
|
|
function getPreset(id) {
|
|
|
|
return presets.filter(function(preset) {
|
|
|
|
return preset.id == id;
|
|
|
|
})[0]
|
|
|
|
}
|
|
|
|
|
|
|
|
function exportSequenceCSV() {
|
|
|
|
var position = 0;
|
2018-12-05 16:44:19 +00:00
|
|
|
return [
|
|
|
|
['preset', 'name', 'time', 'duration', 'speed', 'sleep', 'elevation', 'azimuth', 'zoom']
|
|
|
|
].concat(data.map(function(row) {
|
2018-12-05 16:18:57 +00:00
|
|
|
var r = [];
|
|
|
|
r.push(row.preset)
|
|
|
|
var preset = getPreset(row.preset)
|
2018-12-07 21:01:24 +00:00
|
|
|
if (preset) {
|
|
|
|
r.push(preset.name)
|
|
|
|
} else {
|
|
|
|
r.push(row.preset)
|
|
|
|
}
|
2018-12-05 16:18:57 +00:00
|
|
|
if (row.duration) {
|
|
|
|
position += row.duration
|
|
|
|
r.push(formatDuration(position))
|
|
|
|
r.push(formatDuration(row.duration))
|
|
|
|
} else {
|
|
|
|
r.push('')
|
|
|
|
r.push('')
|
|
|
|
}
|
|
|
|
r.push(row.speed)
|
|
|
|
r.push(row.sleep)
|
2018-12-07 21:01:24 +00:00
|
|
|
if (preset) {
|
|
|
|
r.push(preset.position.elevation)
|
|
|
|
r.push(preset.position.azimuth)
|
|
|
|
r.push(preset.position.absoluteZoom)
|
|
|
|
} else {
|
|
|
|
r.push('')
|
|
|
|
r.push('')
|
|
|
|
r.push('')
|
|
|
|
}
|
2018-12-05 16:18:57 +00:00
|
|
|
return r.join(',');
|
2018-12-05 16:44:19 +00:00
|
|
|
})).join('\n');
|
2018-12-05 16:18:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$('button.export_sequence_csv').on({click: function() {
|
|
|
|
data.forEach(function(seq) {
|
|
|
|
if (!seq.seqid) {
|
|
|
|
seq.seqid = uuidv4()
|
|
|
|
}
|
|
|
|
})
|
2018-12-05 16:31:25 +00:00
|
|
|
var blob = textBlob(exportSequenceCSV(), 'text/csv; charset=utf-8')
|
2018-12-05 16:18:57 +00:00
|
|
|
var url = window.URL.createObjectURL(blob);
|
|
|
|
$(this).parent().attr({
|
|
|
|
href: url, download: 'sequence.csv'
|
|
|
|
});
|
|
|
|
}})
|
|
|
|
|
|
|
|
|
2018-12-04 08:50:29 +00:00
|
|
|
$('button.export_sequence').on({click: function() {
|
|
|
|
data.forEach(function(seq) {
|
|
|
|
if (!seq.seqid) {
|
|
|
|
seq.seqid = uuidv4()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
var blob = textBlob(JSON.stringify(exportSequence(), null, ' '))
|
|
|
|
var url = window.URL.createObjectURL(blob);
|
|
|
|
$(this).parent().attr({
|
|
|
|
href: url, download: 'sequence.json'
|
|
|
|
});
|
|
|
|
}})
|
|
|
|
|
|
|
|
$('button.export_presets').on({click: function() {
|
|
|
|
var blob = textBlob(JSON.stringify(presets, null, ' '))
|
|
|
|
var url = window.URL.createObjectURL(blob);
|
|
|
|
$(this).parent().attr({
|
|
|
|
href: url, download: 'presets.json'
|
|
|
|
});
|
|
|
|
}})
|
2018-12-05 12:58:12 +00:00
|
|
|
$('button.shift_presets').on({click: function() {
|
|
|
|
document.location.href = '/static/shift_presets.html';
|
|
|
|
}});
|
|
|
|
|
2018-12-04 08:50:29 +00:00
|
|
|
$('button.all_presets').on({click: function() {
|
2018-12-05 11:29:49 +00:00
|
|
|
api('getPresets', {}, function(response) {
|
|
|
|
presets = response.result.presets
|
2018-12-05 11:50:08 +00:00
|
|
|
var seq = [].concat(data, presets.filter(function(preset) {
|
|
|
|
return data.filter(function(row) {
|
|
|
|
return row.preset == preset.id
|
|
|
|
}).length == 0
|
|
|
|
}).map(function(preset) {
|
2018-12-05 11:29:49 +00:00
|
|
|
return {
|
|
|
|
preset: preset.id,
|
|
|
|
speed: parseInt($('input.default_speed').val(), 10)
|
|
|
|
}
|
|
|
|
}))
|
2018-12-05 11:50:08 +00:00
|
|
|
|
|
|
|
loadData(seq)
|
2018-12-05 11:29:49 +00:00
|
|
|
})
|
2018-12-04 08:50:29 +00:00
|
|
|
}})
|
|
|
|
|
|
|
|
$('input.import_sequence').on({change: function() {
|
|
|
|
var reader = new FileReader()
|
|
|
|
reader.onload = function(event) {
|
2020-12-06 12:42:13 +00:00
|
|
|
var sequence = JSON.parse(reader.result)
|
|
|
|
api('updateSequence', {sequence: sequence}, function() {})
|
|
|
|
loadData(sequence)
|
2018-12-04 08:50:29 +00:00
|
|
|
}
|
|
|
|
reader.readAsText(this.files[0]);
|
|
|
|
}})
|
|
|
|
$('input.import_presets').on({change: function() {
|
2018-12-04 13:55:00 +00:00
|
|
|
var reader = new FileReader()
|
|
|
|
reader.onload = function(event) {
|
|
|
|
var data = JSON.parse(reader.result)
|
|
|
|
api('setPresets', {
|
2018-12-06 10:44:52 +00:00
|
|
|
'presets': data
|
2018-12-04 13:55:00 +00:00
|
|
|
}, function(response) {
|
|
|
|
presets = response.result.presets
|
|
|
|
})
|
|
|
|
}
|
|
|
|
reader.readAsText(this.files[0]);
|
2018-12-04 08:50:29 +00:00
|
|
|
}})
|
2018-12-05 12:58:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
function shiftPresets(offset, callback) {
|
|
|
|
api('getPresets', {}, function(response) {
|
|
|
|
presets = response.result.presets
|
|
|
|
presets.forEach(function(preset) {
|
|
|
|
if (offset.azimuth) {
|
2018-12-05 16:58:35 +00:00
|
|
|
preset['position']['azimuth'] -= offset.azimuth
|
2018-12-05 12:58:12 +00:00
|
|
|
}
|
|
|
|
if (offset.elevation) {
|
2018-12-05 16:58:35 +00:00
|
|
|
preset['position']['elevation'] -= offset.elevation
|
2018-12-05 12:58:12 +00:00
|
|
|
}
|
|
|
|
if (offset.absoluteZoom) {
|
2018-12-05 16:58:35 +00:00
|
|
|
preset['position']['absoluteZoom'] -= offset.absoluteZoom
|
2018-12-05 12:58:12 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
api('setPresets', {
|
|
|
|
'presets': presets
|
|
|
|
}, function(response) {
|
|
|
|
presets = response.result.presets
|
|
|
|
callback && callback()
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function init() {
|
|
|
|
api('getPresets', {}, function(response) {
|
|
|
|
presets = response.result.presets
|
2020-12-06 12:42:13 +00:00
|
|
|
api('getSequence', {}, function(response) {
|
|
|
|
loadData(response.result.sequence)
|
|
|
|
updateStatus()
|
|
|
|
setInterval(updateStatus, 1000)
|
|
|
|
})
|
2018-12-05 12:58:12 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
function init_shift() {
|
|
|
|
api('getPresets', {}, function(response) {
|
|
|
|
presets = response.result.presets
|
|
|
|
presetSelect().on({
|
|
|
|
change: updateShiftStatus
|
|
|
|
}).appendTo($('body'))
|
|
|
|
$('<pre>').attr({id: 'delta'}).appendTo($('body'))
|
|
|
|
$('<button>').html('Shift All Presets')
|
|
|
|
.appendTo($('body')).on({
|
|
|
|
click: function() {
|
|
|
|
$('body').html('updating presets...')
|
|
|
|
shiftPresets(preset_offset, function() {
|
|
|
|
document.location.href = '/'
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
updateShiftStatus()
|
|
|
|
setInterval(updateShiftStatus, 5000)
|
|
|
|
})
|
|
|
|
}
|
2020-12-05 11:24:41 +00:00
|
|
|
|
|
|
|
function init_ptz() {
|
|
|
|
var ptz = document.querySelector('#ptz')
|
|
|
|
if (ptz) {
|
|
|
|
ptz.querySelectorAll('button').forEach(button => {
|
|
|
|
button.addEventListener('click', event => {
|
|
|
|
var duration = parseFloat(ptz.querySelector('input[name="duration"]').value)
|
|
|
|
var speed = parseInt(ptz.querySelector('input[name="speed"]').value)
|
|
|
|
api('move', {
|
|
|
|
direction: button.dataset.direction,
|
|
|
|
duration: duration,
|
|
|
|
speed: speed
|
|
|
|
}, response=> {})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
2020-12-05 11:55:59 +00:00
|
|
|
api('getPresets', {}, function(response) {
|
|
|
|
presets = response.result.presets
|
|
|
|
var id = 1
|
2020-12-05 12:08:57 +00:00
|
|
|
$('<br>').appendTo($(ptz))
|
2020-12-05 11:55:59 +00:00
|
|
|
presetSelect(true).on({
|
|
|
|
change: event => {
|
|
|
|
id = parseInt(event.target.value)
|
|
|
|
var preset = getPreset(id)
|
|
|
|
name.val(preset ? preset.name : '')
|
|
|
|
}
|
2020-12-05 12:08:57 +00:00
|
|
|
}).appendTo($(ptz))
|
2020-12-05 12:02:55 +00:00
|
|
|
$('<button>').html('Go')
|
2020-12-05 12:08:57 +00:00
|
|
|
.appendTo($(ptz)).on({
|
2020-12-05 12:02:55 +00:00
|
|
|
click: function() {
|
|
|
|
api('camera', {
|
|
|
|
'fast_preset': {id: id}
|
|
|
|
}, function(response) {
|
|
|
|
//console.log(response)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
2020-12-05 12:08:57 +00:00
|
|
|
$('<br>').appendTo($(ptz))
|
|
|
|
$('<br>').appendTo($(ptz))
|
|
|
|
var name = $('<input>').appendTo($(ptz))
|
2021-10-20 08:31:42 +00:00
|
|
|
var preset = getPreset(id)
|
|
|
|
if (preset) {
|
|
|
|
name.val(preset.name)
|
|
|
|
}
|
|
|
|
|
2020-12-05 11:55:59 +00:00
|
|
|
$('<button>').html('Set')
|
2020-12-05 12:08:57 +00:00
|
|
|
.appendTo($(ptz)).on({
|
2020-12-05 11:55:59 +00:00
|
|
|
click: function() {
|
|
|
|
var data = {}
|
|
|
|
if (name.val().length) {
|
|
|
|
data['name'] = name.val()
|
|
|
|
}
|
|
|
|
data['id'] = id
|
|
|
|
api('setPreset', data)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
2020-12-05 11:24:41 +00:00
|
|
|
}
|