354 lines
15 KiB
HTML
354 lines
15 KiB
HTML
<html>
|
|
<head>
|
|
<!-- these 4 files always have to be included -->
|
|
<link rel="stylesheet" type="text/css" href="../../lib/css/materialize.css">
|
|
<link rel="stylesheet" type="text/css" href="../../css/adapter.css"/>
|
|
|
|
<script type="text/javascript" src="../../lib/js/jquery-3.2.1.min.js"></script>
|
|
<script type="text/javascript" src="../../socket.io/socket.io.js"></script>
|
|
|
|
<!-- these files always have to be included -->
|
|
<script type="text/javascript" src="../../js/translate.js"></script>
|
|
<script type="text/javascript" src="../../lib/js/materialize.js"></script>
|
|
<script type="text/javascript" src="../../js/adapter-settings.js"></script>
|
|
<script type="text/javascript" src="words.js"></script>
|
|
<style>
|
|
.m .col .select-wrapper+label {
|
|
top: -26px;
|
|
}
|
|
.m span{
|
|
font-size: 0.9em;
|
|
}
|
|
</style>
|
|
<!-- you have to define 2 functions in the global scope: -->
|
|
<script type="text/javascript">
|
|
var namespace = 'onvif.' + instance,
|
|
namespaceLen = namespace.length;
|
|
// the function loadSettings has to exist ...
|
|
function load(settings, onChange) {
|
|
// example: select elements with id=key and class=value and insert value
|
|
if (!settings) return;
|
|
$('.value').each(function () {
|
|
var $key = $(this);
|
|
var id = $key.attr('id');
|
|
if ($key.attr('type') === 'checkbox') {
|
|
// do not call onChange direct, because onChange could expect some arguments
|
|
$key.prop('checked', settings[id]).change(function() {
|
|
onChange();
|
|
});
|
|
} else {
|
|
// do not call onChange direct, because onChange could expect some arguments
|
|
$key.val(settings[id]).change(function() {
|
|
onChange();
|
|
}).keyup(function() {
|
|
onChange();
|
|
});
|
|
}
|
|
});
|
|
onChange(false);
|
|
M.updateTextFields(); // function Materialize.updateTextFields(); to reinitialize all the Materialize labels on the page if you are dynamically adding inputs.
|
|
}
|
|
|
|
// ... and the function save has to exist.
|
|
// you have to make sure the callback is called with the settings object as first param!
|
|
function save(callback) {
|
|
// example: select elements with class=value and build settings object
|
|
var obj = {};
|
|
$('.value').each(function () {
|
|
var $this = $(this);
|
|
if ($this.attr('type') === 'checkbox') {
|
|
obj[$this.attr('id')] = $this.prop('checked');
|
|
} else {
|
|
obj[$this.attr('id')] = $this.val();
|
|
}
|
|
});
|
|
callback(obj);
|
|
}
|
|
|
|
function startDiscovery(){
|
|
var options = {
|
|
start_range: $('#start_range').val(),
|
|
end_range: $('#end_range').val(),
|
|
ports: $('#ports').val(),
|
|
user: $('#user').val(),
|
|
pass: $('#pass').val()
|
|
};
|
|
console.log(options);
|
|
sendTo(null, 'discovery', options, function (result) {
|
|
console.log(result);
|
|
});
|
|
}
|
|
$(document).ready(function(){
|
|
$('#discovery').off('click').on('click', function () {
|
|
startDiscovery();
|
|
});
|
|
$('.modal').modal();
|
|
getDevices();
|
|
socket.on('objectChange', function (id, obj) {
|
|
if (id.substring(0, namespaceLen) !== namespace) return;
|
|
if (obj && obj.type == "device") {
|
|
getDevices();
|
|
}
|
|
});
|
|
// react to changes
|
|
socket.on('stateChange', function (id, state) {
|
|
// only watch our own states
|
|
if (id.substring(0, namespaceLen) !== namespace) return;
|
|
console.log("State change announced: " + id + " and obj = " + JSON.stringify(state));
|
|
if (state) {
|
|
if (id.match(/\.discoveryRunning$/)) {
|
|
if (state.val) {
|
|
$('#discovery').addClass('pulse disabled');
|
|
} else {
|
|
$('#discovery').removeClass('pulse disabled');
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
function getCard(dev) {
|
|
var title = dev.common.name,
|
|
id = dev._id,
|
|
info = '',
|
|
buttons = '<a name="delete" class="btn-floating waves-effect waves-light right hoverable black"><i class="material-icons tiny">delete</i></a>',
|
|
card = '<div id="' + id + '" class="device col s12 m6 l4 xl3">'+
|
|
'<div class="card hoverable">'+
|
|
'<div class="card-content">'+
|
|
'<span class="card-title">'+title+'</span>'+
|
|
'<div class="card-image"><img id="img' + id + '" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="/></div>'+
|
|
info+
|
|
buttons+
|
|
'</div>'+
|
|
'</div>'+
|
|
'</div>';
|
|
return card;
|
|
}
|
|
|
|
function showDevices(devices) {
|
|
var html = '';
|
|
for (var i=0;i < devices.length; i++) {
|
|
var d = devices[i];
|
|
var card = getCard(d);
|
|
html += card;
|
|
}
|
|
$('#devices').html(html);
|
|
for (var i=0;i < devices.length; i++) {
|
|
var d = devices[i];
|
|
getSnapshot(d._id);
|
|
}
|
|
$("a.btn-floating[name='delete']").click(function() {
|
|
var dev_block = $(this).parents("div.device"),
|
|
id = dev_block.attr("id"),
|
|
name = dev_block.find(".card-title").text();
|
|
deleteConfirmation(id, name);
|
|
});
|
|
// $("a.btn-floating[name='edit']").click(function(e) {
|
|
// var dev_block = $(this).parents("div.device"),
|
|
// id = dev_block.attr("id"),
|
|
// name = dev_block.find(".card-title").text();
|
|
// // editName(id, name);
|
|
// openReval(e, id, name);
|
|
// });
|
|
// $("a.btn[name='done']").click(function(e) {
|
|
// var dev_block = $(this).parents("div.device"),
|
|
// id = dev_block.attr("id"),
|
|
// name = dev_block.find("input").val();
|
|
// closeReval(e, id, name);
|
|
// });
|
|
// $("a.btn-flat[name='close']").click(function(e) {
|
|
// closeReval(e);
|
|
// });
|
|
}
|
|
|
|
function deleteConfirmation(id, name) {
|
|
var text = 'Do you really whant to delete device "'+name+'" ('+id+')?';
|
|
$('#modaldelete').find("h3").text("Delete confirmation");
|
|
$('#modaldelete').find("p").text(text);
|
|
$("#modaldelete a.btn[name='yes']").unbind("click");
|
|
$("#modaldelete a.btn[name='yes']").click(function(e) {
|
|
deleteDevice(id);
|
|
});
|
|
$('#modaldelete').modal('open');
|
|
}
|
|
|
|
function deleteDevice(id) {
|
|
sendTo(null, 'deleteDevice', {id: id}, function (msg) {
|
|
//console.log(msg);
|
|
if (msg) {
|
|
if (msg.error) {
|
|
showMessage(msg.error.code, _('Error'), 'alert');
|
|
} else {
|
|
getDevices();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function getDevices() {
|
|
sendTo(null, 'getDevices', {}, function (msg) {
|
|
//console.log(msg);
|
|
if (msg) {
|
|
if (msg.error) {
|
|
showMessage(msg.error, _('Error'), 'alert');
|
|
} else {
|
|
showDevices(msg);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function arrayBufferDataUri(raw) {
|
|
var base64 = '';
|
|
var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
var bytes = new Uint8Array(raw.rawImage);
|
|
var byteLength = bytes.byteLength;
|
|
var byteRemainder = byteLength % 3;
|
|
var mainLength = byteLength - byteRemainder;
|
|
var a, b, c, d;
|
|
var chunk;
|
|
|
|
// Main loop deals with bytes in chunks of 3
|
|
for (var i = 0; i < mainLength; i = i + 3) {
|
|
// Combine the three bytes into a single integer
|
|
chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
|
|
// Use bitmasks to extract 6-bit segments from the triplet
|
|
a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18
|
|
b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12
|
|
c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6
|
|
d = chunk & 63; // 63 = 2^6 - 1
|
|
// Convert the raw binary segments to the appropriate ASCII encoding
|
|
base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
|
|
}
|
|
// Deal with the remaining bytes and padding
|
|
if (byteRemainder == 1) {
|
|
chunk = bytes[mainLength];
|
|
a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2;
|
|
// Set the 4 least significant bits to zero
|
|
b = (chunk & 3) << 4 // 3 = 2^2 - 1;
|
|
base64 += encodings[a] + encodings[b] + '==';
|
|
}
|
|
else if (byteRemainder == 2) {
|
|
chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1];
|
|
a = (chunk & 16128) >> 8 // 16128 = (2^6 - 1) << 8;
|
|
b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4;
|
|
// Set the 2 least significant bits to zero
|
|
c = (chunk & 15) << 2 // 15 = 2^4 - 1;
|
|
base64 += encodings[a] + encodings[b] + encodings[c] + '=';
|
|
}
|
|
return "data:"+raw.mimeType+";base64," + base64;
|
|
}
|
|
|
|
function getSnapshot(id){
|
|
sendTo(null, 'getSnapshot', {id: id}, function (msg) {
|
|
if (msg) {
|
|
if (msg.error) {
|
|
showMessage(msg.error, _('Error'), 'alert');
|
|
} else {
|
|
$("[id='img"+id+"']").attr('src', arrayBufferDataUri(msg));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<!-- you have to put your config page in a div with id adapter-container -->
|
|
<div class="m adapter-container">
|
|
<div class="row">
|
|
<!-- Forms are the standard way to receive user inputted data.
|
|
Learn more http://materializecss.com/forms.html-->
|
|
<div class="row valign-wrapper">
|
|
<div class="col s6">
|
|
<img src="onvif_logo.png">
|
|
</div>
|
|
<div class="col s6 right-align">
|
|
<!--<a class="btn-floating waves-effect waves-light btn-large green tooltipped center-align hoverable modal-trigger" href="#modal_add"><i class="material-icons large">add</i></a>-->
|
|
<a class="btn-floating waves-effect waves-light btn-large blue tooltipped center-align hoverable modal-trigger" href="#modal_discovery"><i class="material-icons large">youtube_searched_for</i></a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="devices" class="row">
|
|
</div>
|
|
</div>
|
|
<div class="materialize-dialogs m">
|
|
<div id="modal_discovery" class="modal">
|
|
<div class="modal-content">
|
|
<div class="title translate">Scan cameras</div>
|
|
<div class="row">
|
|
<div class="input-field col s12 m6 l4 xl3">
|
|
<input class="value" type="text" id="start_range"/>
|
|
<label class="translate" for="start_range" data-lang="startRange">Start range</label>
|
|
</div>
|
|
<div class="input-field col s12 m6 l4 xl3">
|
|
<input class="value" type="text" id="end_range"/>
|
|
<label class="translate" for="end_range">End range</label>
|
|
</div>
|
|
<div class="input-field col s12 m6 l4 xl3">
|
|
<input class="value" type="text" id="ports"/>
|
|
<label class="translate" for="ports">Port list</label>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="input-field col s12 m6 l4 xl4">
|
|
<input class="value" type="text" id="user"/>
|
|
<label class="translate" for="user">User name</label>
|
|
</div>
|
|
<div class="input-field col s12 m6 l4 xl4">
|
|
<input class="value" type="password" id="pass"/>
|
|
<label class="translate" for="pass">Password</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<a id="discovery" href="#!" class="modal-action modal-close waves-effect waves-green btn-flat translate" data-result="true">Start scan</a>
|
|
<a href="#!" class="modal-action modal-close waves-effect waves-green btn-flat translate">Cancel</a>
|
|
</div>
|
|
</div>
|
|
<div class="materialize-dialogs m">
|
|
<div id="modal_add" class="modal">
|
|
<div class="modal-content">
|
|
<div class="title translate">Add camera</div>
|
|
<div class="row">
|
|
<div class="input-field col s12 m6 l4 xl3">
|
|
<input class="value" id="ip"/>
|
|
<label class="translate" for="ip">IP</label>
|
|
</div>
|
|
<div class="input-field col s12 m6 l4 xl3">
|
|
<input class="value" id="port"/>
|
|
<label class="translate" for="port">Port</label>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="input-field col s12 m6 l4 xl4">
|
|
<input class="value" id="c_user"/>
|
|
<label class="translate" for="c_user">User name</label>
|
|
</div>
|
|
<div class="input-field col s12 m6 l4 xl4">
|
|
<input class="value" id="c_pass"/>
|
|
<label class="translate" for="c_pass">Password</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<a id="add" href="#!" class="modal-action modal-close waves-effect waves-green btn-flat translate" data-result="true">Create</a>
|
|
<a href="#!" class="modal-action modal-close waves-effect waves-green btn-flat translate">Cancel</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="materialize-dialogs m">
|
|
<div id="modaldelete" class="modal">
|
|
<div class="modal-content">
|
|
<h3>Modal Header</h3>
|
|
<p>A bunch of text</p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<a name="yes" href="#!" class="modal-action modal-close waves-effect waves-green btn green">Yes</a>
|
|
<a href="#!" class="modal-action modal-close waves-effect waves-red btn-flat">Cancel</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|