1015 lines
44 KiB
HTML
1015 lines
44 KiB
HTML
<html>
|
|
|
|
<link rel="stylesheet" type="text/css" href="../../lib/css/themes/jquery-ui/redmond/jquery-ui.min.css"/>
|
|
|
|
<script type="text/javascript" src="../../lib/js/jquery-1.11.1.min.js"></script>
|
|
<script type="text/javascript" src="../../lib/js/jquery-ui.min.js"></script>
|
|
|
|
<script type="text/javascript" src="../../socket.io/socket.io.js"></script>
|
|
|
|
<link rel="stylesheet" type="text/css" href="./lib/css/jsgrid.css"/>
|
|
<link rel="stylesheet" type="text/css" href="./lib/css/jsgrid-theme.css"/>
|
|
<script type="text/javascript" src="./lib/js/jsgrid.js"></script>
|
|
<script type="text/javascript" src="./lib/js/grid.locale-cn.js"></script>
|
|
|
|
|
|
<link rel="stylesheet" type="text/css" href="../../css/adapter.css"/>
|
|
<script type="text/javascript" src="../../js/translate.js"></script>
|
|
<script type="text/javascript" src="../../js/adapter-settings.js"></script>
|
|
<script type="text/javascript" src="words.js"></script>
|
|
|
|
<link rel="stylesheet" type="text/css" href="./lib/css/my.css"/>
|
|
|
|
|
|
<script type="text/javascript">
|
|
var onChange = null;
|
|
var activePage = '';
|
|
|
|
var offsets = {
|
|
disInputs: 10001,
|
|
coils: 1,
|
|
inputRegs: 30001,
|
|
holdingRegs: 40001
|
|
};
|
|
var isDirect = false;
|
|
|
|
var typeItemsLen = {
|
|
'uint8be': 1,
|
|
'uint8le': 1
|
|
};
|
|
|
|
var attempts = 0;
|
|
var ignoreDialog = 0;
|
|
|
|
function getComPorts(actualValue) {
|
|
var timeout = setTimeout(function () {
|
|
getComPorts(actualValue);
|
|
}, 2000);
|
|
|
|
sendTo(null, 'listUart', null, function (list) {
|
|
if (timeout) {
|
|
clearTimeout(timeout);
|
|
timeout = null;
|
|
}
|
|
if (!list || !list.length) {
|
|
attempts++;
|
|
if (attempts < 10) {
|
|
setTimeout(function () {
|
|
getComPorts(actualValue);
|
|
}, 1000);
|
|
}
|
|
return;
|
|
}
|
|
var $comName = $('#modbus_comName');
|
|
var text = '<option value="">' + _('Select port') + '</option>';
|
|
for (var j = 0; j < list.length; j++) {
|
|
if (list[j].comName === 'Not available') {
|
|
text = '<option value="" selected>' + _('Not available') + '</option>';
|
|
$comName.prop('disabled', true);
|
|
break;
|
|
} else {
|
|
text += '<option value="' + list[j].comName + '" ' + ((actualValue === list[j].comName) ? 'selected' : '') + '>' + list[j].comName + '</option>';
|
|
}
|
|
}
|
|
$comName.html(text);
|
|
});
|
|
}
|
|
|
|
function getExport(data, id, delimiter) {
|
|
delimiter = delimiter || '\t';
|
|
var text = '';
|
|
|
|
text += 'address' + delimiter +
|
|
'name' + delimiter +
|
|
'description' + delimiter;
|
|
if (id !== 'coils' && id !== 'disInputs') {
|
|
text += 'unit' + delimiter;
|
|
text += 'type' + delimiter;
|
|
text += 'len' + delimiter;
|
|
text += 'factor' + delimiter;
|
|
text += 'offset' + delimiter;
|
|
}
|
|
text += 'role' + delimiter +
|
|
'room' + delimiter;
|
|
|
|
if (id === 'coils' || id === 'holdingRegs') {
|
|
text += 'poll' + delimiter +
|
|
'wp';
|
|
if (!data.params.slave) {
|
|
text += delimiter + 'cw';
|
|
}
|
|
}
|
|
text += '\n';
|
|
|
|
for (var i = 0; i < data[id].length; i++) {
|
|
text += data[id][i]._address + delimiter;
|
|
text += (data[id][i].name || '') + delimiter;
|
|
text += (data[id][i].description || '') + delimiter;
|
|
if (id !== 'coils' && id !== 'disInputs') {
|
|
text += (data[id][i].unit || '') + delimiter;
|
|
text += (data[id][i].type || '') + delimiter;
|
|
text += (data[id][i].len || 1) + delimiter;
|
|
text += (data[id][i].factor || 1) + delimiter;
|
|
text += (data[id][i].offset || 0) + delimiter;
|
|
}
|
|
text += (data[id][i].role || '') + delimiter;
|
|
text += (data[id][i].room || '') + delimiter;
|
|
if (id === 'coils' || id === 'holdingRegs') {
|
|
text += (data[id][i].poll ? 'true' : 'false') + delimiter;
|
|
text += (data[id][i].wp ? 'true' : 'false') + delimiter;
|
|
if (!data.params.slave) {
|
|
text += (data[id][i].cw ? 'true' : 'false') + delimiter;
|
|
}
|
|
}
|
|
text += '\n';
|
|
}
|
|
return text;
|
|
}
|
|
|
|
function getImport(data, id, text) {
|
|
var delimiter;
|
|
if (text.indexOf('\t') !== -1) {
|
|
delimiter = '\t';
|
|
} else if (text.indexOf(';') !== -1) {
|
|
delimiter = ';';
|
|
} else {
|
|
delimiter = ' ';
|
|
}
|
|
var lines = text.split('\r\n');
|
|
if (lines.length === 1) {
|
|
lines = text.split('\n');
|
|
if (lines.length === 1) {
|
|
lines = text.split('\r');
|
|
}
|
|
}
|
|
var isAliases = $('#modbus_showAliases').prop('checked');
|
|
var mapping;
|
|
if (id !== 'coils' && id !== 'disInputs') {
|
|
mapping = ['address', 'name', 'description', 'unit', 'type', 'len', 'factor', 'offset', 'role', 'room'];
|
|
} else {
|
|
mapping = ['address', 'name', 'description', 'role', 'room'];
|
|
}
|
|
|
|
for (var i = 0; i < lines.length; i++) {
|
|
var parts = lines[i].split(delimiter);
|
|
if (parts.length === 1) continue;
|
|
if (parseInt(parts[0].trim(), 10).toString() !== parts[0]) {
|
|
// may be it is fields description
|
|
mapping = parts;
|
|
continue;
|
|
}
|
|
var obj = {};
|
|
var j = 0;
|
|
for (var m = 0; m < mapping.length; m++) {
|
|
var val = parts[m].trim();
|
|
|
|
if (mapping[m] === 'address') {
|
|
obj._address = parseInt(val, 10) || 0;
|
|
obj.address = obj._address;
|
|
} else {
|
|
obj[mapping[m]] = val || '';
|
|
}
|
|
}
|
|
if (typeItemsLen[obj.type]) obj.len = typeItemsLen[obj.type];
|
|
data[id].push(obj);
|
|
}
|
|
$('#modbus_' + id).jsGrid('render');
|
|
}
|
|
|
|
function switchOneType(data, id) {
|
|
var isDirect = $('#modbus_directAddresses').prop('checked');
|
|
if ($('#modbus_showAliases').prop('checked')) {
|
|
for (var i = 0; i < data[id].length; i++) {
|
|
data[id][i]._address = address2alias(id, data[id][i].address, isDirect);
|
|
}
|
|
} else {
|
|
for (var i = 0; i < data[id].length; i++) {
|
|
data[id][i]._address = parseInt(data[id][i].address, 10) || 0;
|
|
}
|
|
}
|
|
$('#modbus_' + id).jsGrid('render');
|
|
}
|
|
|
|
function switchAll(data) {
|
|
switchOneType(data, 'disInputs');
|
|
switchOneType(data, 'coils');
|
|
switchOneType(data, 'inputRegs');
|
|
switchOneType(data, 'holdingRegs');
|
|
if ($('#modbus_showAliases').prop('checked')) {
|
|
$('.offsets').show();
|
|
} else {
|
|
$('.offsets').hide();
|
|
}
|
|
}
|
|
|
|
function recalculate(data, id, oldOffset, newOffset) {
|
|
if ($('#modbus_showAliases').prop('checked')) {
|
|
for (var i = 0; i < data[id].length; i++) {
|
|
data[id][i].address = parseInt(data[id][i].address, 10) || 0;
|
|
data[id][i].address += (oldOffset - newOffset);
|
|
}
|
|
}
|
|
}
|
|
|
|
function initTabs(onchange, data) {
|
|
if (!data) {
|
|
data = {};
|
|
$.each($('.modbus-grid'), function () {
|
|
var id = $(this).attr('id');
|
|
var key = id.split('_')[1];
|
|
|
|
if ($(this).data('JSGrid')._editingRow) {
|
|
$(this).jsGrid('updateItem');
|
|
}
|
|
|
|
data[key] = $(this).jsGrid('option', 'data');
|
|
});
|
|
}
|
|
|
|
|
|
getEnums('rooms', function (err, rooms) {
|
|
$.each($('.modbus-grid'), function () {
|
|
var _id = $(this).attr('id');
|
|
|
|
// todo read roles and expand this list
|
|
var roleItems = [
|
|
{value: '', text: ''},
|
|
{value: 'value', text: 'value'},
|
|
{value: 'level', text: 'level'},
|
|
{value: 'state', text: 'state'},
|
|
{value: 'switch', text: 'switch'},
|
|
{value: 'value.temperature', text: 'value.temperature'},
|
|
{value: 'value.humidity', text: 'value.humidity'},
|
|
{value: 'value.brightness', text: 'value.brightness'},
|
|
{value: 'value.uv', text: 'value.uv'},
|
|
{value: 'value.pressure', text: 'value.pressure'},
|
|
{value: 'value.battery', text: 'value.battery'},
|
|
{value: 'value.valve', text: 'value.valve'},
|
|
{value: 'value.time', text: 'value.time'},
|
|
{value: 'value.interval', text: 'value.interval'},
|
|
{value: 'value.window', text: 'value.window'},
|
|
{value: 'button', text: 'button'},
|
|
{value: 'indicator', text: 'indicator'},
|
|
{value: 'level.dimmer', text: 'level.dimmer'},
|
|
{value: 'level.valve', text: 'level.valve'},
|
|
{value: 'level.blind', text: 'level.blind'},
|
|
{value: 'level.temperature', text: 'level.temperature'},
|
|
{value: 'level.interval', text: 'level.interval'}
|
|
];
|
|
|
|
var typeItems = [
|
|
{value: 'string', text: 'string'},
|
|
{value: 'number', text: 'number'},
|
|
{value: 'boolean', text: 'boolean'}
|
|
];
|
|
|
|
var roomsItems = [{value: '', text: ''}];
|
|
for (var room in rooms) {
|
|
if (rooms.hasOwnProperty(room)) {
|
|
roomsItems.push({value: room, text: rooms[room].common.name || room.substring('enum.rooms.'.length)});
|
|
}
|
|
}
|
|
var fields = [
|
|
{name: '_address' , title: _('Address'), type: 'text', width: '110px', sorter: 'number'},
|
|
{name: 'deviceId' , title: _('deviceId'), type: 'text', width: '60px', sorter: 'number'},
|
|
{name: 'name' , title: _('Name'), type: 'text', width: '*'},
|
|
{name: 'description', title: _('Description'), type: 'text', width: '*'},
|
|
{name: 'value', title: _('Value'), type: 'text', width: '*'},
|
|
//{name: 'unit' , title: _('Unit'), type: 'text', width: '50px'},
|
|
{name: 'type' , title: _('Type'), type: 'select', width: '200px', items: typeItems, valueField: 'value', textField: 'text'},
|
|
//{name: 'len' , title: _('Length'), type: 'text', width: '50px'},
|
|
//{name: 'factor' , title: _('Factor'), type: 'text', width: '50px'},
|
|
//{name: 'offset' , title: _('Offset'), type: 'text', width: '50px'},
|
|
{name: 'role' , title: _('Role'), type: 'select', width: '100px', items: roleItems, valueField: 'value', textField: 'text'},
|
|
{name: 'room' , title: _('Room'), type: 'select', width: '100px', items: roomsItems, valueField: 'value', textField: 'text'},
|
|
//{name: 'poll' , title: _('poll'), type: 'checkbox', width: '35px'},
|
|
//{name: 'wp' , title: _('WP'), type: 'checkbox', width: '35px'},
|
|
{ type: 'control', width: '80px'}
|
|
];
|
|
if (_id === 'modbus_disInputs' || _id === 'modbus_inputRegs') {
|
|
fields.splice(11, 3);
|
|
}
|
|
if (_id === 'modbus_coils' || _id === 'modbus_disInputs') {
|
|
fields.splice(4, 5);
|
|
}
|
|
if (parseInt($('#modbus_slave').val())) {
|
|
fields.splice(13, 1);
|
|
fields.splice(1, 1);
|
|
} else if (!$('#modbus_multiDeviceId').prop('checked')) {
|
|
fields.splice(1, 1);
|
|
}
|
|
|
|
var g = $('#' + _id).jsGrid({
|
|
width: 'auto',
|
|
height: 'auto',
|
|
inserting: true,
|
|
editing: true,
|
|
sorting: true,
|
|
heading: true,
|
|
paging: false,
|
|
deleteConfirm: function (el, item, cb) {
|
|
if (!ignoreDialog || Date.now() - ignoreDialog > 60000) {
|
|
var buttons = {};
|
|
buttons[_('Delete')] = function() {
|
|
if ($('#delete_ignore_dialog').prop('checked')) {
|
|
ignoreDialog = Date.now();
|
|
}
|
|
|
|
cb && cb(true);
|
|
$( this ).dialog('close');
|
|
};
|
|
buttons[_('Cancel')] = function() {
|
|
cb && cb(false);
|
|
$( this ).dialog('close');
|
|
};
|
|
|
|
$('#delete_ignore_dialog').prop('checked', false);
|
|
|
|
$("#delete-dlg").dialog({
|
|
resizable: false,
|
|
height: 'auto',
|
|
title: _('Delete address'),
|
|
width: 500,
|
|
modal: true,
|
|
buttons: buttons
|
|
});
|
|
} else {
|
|
cb && cb(true);
|
|
}
|
|
},
|
|
data: data[_id.split('_')[1]],
|
|
fields: fields,
|
|
|
|
editRowRenderer: function(item) {
|
|
var $result = $('<tr>').addClass(this.editRowClass);
|
|
|
|
this._eachField(function(field) {
|
|
$('<td>').addClass(field.css)
|
|
.appendTo($result)
|
|
.append(field.editTemplate ? field.editTemplate(item ? item[field.name] : '', item) : '')
|
|
.width(field.width || 'auto').keypress(function (e) {
|
|
if (e.which === 13) {
|
|
$('#' + _id).jsGrid('updateItem');
|
|
}
|
|
onchange();
|
|
});
|
|
});
|
|
return $result;
|
|
},
|
|
onItemUpdated: function (obj) {
|
|
/* {grid, row, item, itemIndex, previousItem}*/
|
|
var id = obj.grid._body.parent().attr('id');
|
|
var changed = false;
|
|
if (obj.item.wp && !obj.item.poll) {
|
|
obj.item.poll = true;
|
|
changed = true;
|
|
}
|
|
if (parseInt(obj.item.address, 10).toString() !== obj.item.address.toString()) changed = true;
|
|
obj.item._address = parseInt(obj.item._address, 10);
|
|
|
|
if ($('#modbus_showAliases').prop('checked')) {
|
|
var isDirect = $('#modbus_directAddresses').prop('checked');
|
|
obj.item.address = alias2address(id.split('_').pop(), obj.item._address, isDirect);
|
|
} else {
|
|
obj.item.address = obj.item._address;
|
|
}
|
|
|
|
if (obj.item.type === '') {
|
|
obj.item.type = typeItems[1].value;
|
|
changed = true;
|
|
}
|
|
|
|
// update length
|
|
if (obj.item.type === 'string' || obj.item.type === 'stringle') {
|
|
if (obj.item.factor !== '') {
|
|
obj.item.factor = '';
|
|
changed = true;
|
|
}
|
|
if (obj.item.offset !== '') {
|
|
obj.item.offset = '';
|
|
changed = true;
|
|
}
|
|
|
|
obj.item.len = parseInt(obj.item.len, 10) || 0;
|
|
if (!obj.item.len) {
|
|
obj.item.len = 2;
|
|
changed = true;
|
|
}
|
|
} else if (typeItemsLen[obj.item.type]) {
|
|
obj.item.len = parseInt(obj.item.len, 10);
|
|
if (obj.item.len != typeItemsLen[obj.item.type]) {
|
|
obj.item.len = typeItemsLen[obj.item.type];
|
|
changed = true;
|
|
}
|
|
|
|
if (parseFloat(obj.item.factor).toString() !== obj.item.factor.toString()) {
|
|
obj.item.factor = parseFloat(obj.item.factor) || 1;
|
|
changed = true;
|
|
}
|
|
if (parseFloat(obj.item.offset).toString() !== obj.item.offset.toString()) {
|
|
obj.item.offset = parseFloat(obj.item.offset) || 0;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (!obj.item.role && obj.item.type !== 'string' && obj.item.type !== 'stringle') {
|
|
if (id === 'modbus_disInputs') {
|
|
obj.item.role = 'status';
|
|
} else if (id === 'modbus_coils') {
|
|
obj.item.role = 'button';
|
|
} else if (id === 'modbus_inputRegs') {
|
|
obj.item.role = 'value';
|
|
} else if (id === 'modbus_holdingRegs') {
|
|
obj.item.role = 'level';
|
|
}
|
|
changed = true;
|
|
}
|
|
|
|
if (changed) this.render();
|
|
|
|
onchange();
|
|
},
|
|
onItemInserting: function (obj) {
|
|
if (obj.item.poll !== undefined) {
|
|
obj.item.poll = true;
|
|
}
|
|
// find automatically next address
|
|
var id = obj.grid._body.parent().attr('id').split('_')[1];
|
|
if (data[id].length) {
|
|
var max = 0;
|
|
obj.item.role = data[id][data[id].length - 1].role;
|
|
obj.item.poll = data[id][data[id].length - 1].poll;
|
|
obj.item.wp = data[id][data[id].length - 1].wp;
|
|
obj.item.cw = data[id][data[id].length - 1].cw;
|
|
obj.item.type = data[id][data[id].length - 1].type;
|
|
obj.item.len = data[id][data[id].length - 1].len;
|
|
obj.item.factor = data[id][data[id].length - 1].factor;
|
|
obj.item.offset = data[id][data[id].length - 1].offset;
|
|
obj.item.deviceId = data[id][data[id].length - 1].deviceId;
|
|
|
|
var len;
|
|
var defaultDeviceId = parseInt($('#modbus_deviceId').val(), 10) || 1;
|
|
var actualDeviceId = parseInt(obj.item.deviceId, 10);
|
|
if (!actualDeviceId) actualDeviceId = defaultDeviceId;
|
|
|
|
for (var a = 0; a < data[id].length; a++) {
|
|
var deviceId = parseInt(data[id][a].deviceId, 10);
|
|
if (!deviceId) deviceId = defaultDeviceId;
|
|
if (deviceId !== actualDeviceId) continue;
|
|
if (!obj.item.type) {
|
|
len = 1;
|
|
} else if (obj.item.type !== 'string' && obj.item.type !== 'stringle') {
|
|
len = typeItemsLen[obj.item.type];
|
|
} else {
|
|
len = obj.item.len;
|
|
}
|
|
data[id][a]._address = parseInt(data[id][a]._address, 10);
|
|
|
|
if (data[id][a]._address + len > max) max = data[id][a]._address + len;
|
|
}
|
|
obj.item._address = max;
|
|
|
|
if ($('#modbus_showAliases').prop('checked')) {
|
|
obj.item.address = alias2address(id, parseInt(obj.item._address, 10), isDirect);
|
|
} else {
|
|
obj.item.address = obj.item._address;
|
|
}
|
|
|
|
} else {
|
|
if ($('#modbus_showAliases').prop('checked')) {
|
|
if (id === 'disInputs') {
|
|
obj.item._address = data.params.disInputsOffset;
|
|
} else if (id === 'coils') {
|
|
obj.item._address = data.params.coilsOffset;
|
|
} else if (id === 'inputRegs') {
|
|
obj.item._address = data.params.inputRegsOffset;
|
|
} else if (id === 'holdingRegs') {
|
|
obj.item._address = data.params.holdingRegsOffset;
|
|
}
|
|
obj.item.address = alias2address(id, obj.item._address, isDirect);
|
|
} else {
|
|
obj.item.address = 0;
|
|
obj.item._address = 0;
|
|
}
|
|
|
|
if (id === 'inputRegs' || 'holdingRegs') {
|
|
obj.item.factor = 1;
|
|
obj.item.offset = 0;
|
|
obj.item.type = 'uint16be';
|
|
obj.item.len = '';
|
|
}
|
|
}
|
|
|
|
onchange();
|
|
},
|
|
onItemDeleted: function (obj) {
|
|
onchange();
|
|
}
|
|
});
|
|
g.data('JSGrid')._editRow = function($row) {
|
|
if(this._editingRow) {
|
|
this.updateItem();
|
|
}
|
|
|
|
var item = $row.data('JSGridItem');
|
|
if (!item) return;
|
|
var $editRow = this._createEditRow(item);
|
|
|
|
this._editingRow = $row;
|
|
$row.hide();
|
|
$editRow.insertAfter($row);
|
|
$row.data('JSGridEditRow', $editRow);
|
|
};
|
|
|
|
setTimeout(function () {
|
|
// add custom titles
|
|
$('.jsgrid-header-sortable').each(function () {
|
|
if ($(this).text() === _('poll')) {
|
|
$(this).attr('title', _('Enable polling of data point'));
|
|
} else
|
|
if ($(this).text() === _('WP')) {
|
|
$(this).attr('title', _('Write pulses (true=>false edge)'));
|
|
} else
|
|
if ($(this).text() === _('CW')) {
|
|
$(this).attr('title', _('Cyclic write'));
|
|
}
|
|
});
|
|
}, 1000);
|
|
});
|
|
|
|
switchAll(data);
|
|
});
|
|
}
|
|
|
|
function load(settings, onchange) {
|
|
$('#btn_loadsymbole').button().click(function () {
|
|
$('#symol_import').trigger('click')
|
|
});
|
|
|
|
$('#btn_loaddb').button().click(function () {
|
|
$('#db_import').trigger('click')
|
|
});
|
|
|
|
$('.btn_toggle_pool').button().click(function (e, ui) {
|
|
var grid = $(this).parent().data('grid');
|
|
var $grid = $('#' + grid);
|
|
|
|
var data = $grid.jsGrid('option', 'data');
|
|
$.each(data, function () {
|
|
this.poll = !this.poll;
|
|
});
|
|
|
|
$grid.jsGrid('option', 'data', data);
|
|
onChange();
|
|
});
|
|
|
|
$('.btn_toggle_rw').button().click(function () {
|
|
var grid = $(this).parent().data('grid');
|
|
var $grid = $('#' + grid);
|
|
var data = $grid.jsGrid('option', 'data');
|
|
$.each(data, function () {
|
|
this.RW = !this.RW;
|
|
});
|
|
|
|
$grid.jsGrid('option', 'data', data);
|
|
onChange();
|
|
|
|
});
|
|
|
|
$('.btn_toggle_wp').button().click(function () {
|
|
var grid = $(this).parent().data('grid');
|
|
var $grid = $('#' + grid);
|
|
var data = $grid.jsGrid('option', 'data');
|
|
|
|
$.each(data, function () {
|
|
this.wp = !this.wp;
|
|
});
|
|
|
|
$grid.jsGrid('option', 'data', data);
|
|
onChange();
|
|
});
|
|
|
|
var $adapterContainer = $('#adapter-container');
|
|
$adapterContainer.tabs({
|
|
activate: function (event, ui) {
|
|
switch(ui.newPanel.selector) {
|
|
case '#modbus_tab_g':
|
|
activePage = 0;
|
|
break;
|
|
case '#modbus_tab_regsis_inputs':
|
|
activePage = 1;
|
|
break;
|
|
case '#modbus_tab_coils':
|
|
activePage = 2;
|
|
break;
|
|
case '#modbus_tab_input_regs':
|
|
activePage = 3;
|
|
break;
|
|
case '#modbus_tab_holding_regs':
|
|
activePage = 4;
|
|
break;
|
|
default:
|
|
activePage = 0;
|
|
break;
|
|
}
|
|
if (typeof localStorage !== 'undefined') {
|
|
localStorage['modbuspage'] = activePage.toString();
|
|
}
|
|
}
|
|
});
|
|
|
|
$('.btn_export').button({
|
|
icons: {primary: 'ui-icon-circle-minus'},
|
|
text: false
|
|
})
|
|
.attr('title', _('Export to CSV'))
|
|
.css({width: 24, height: 24})
|
|
.click(function () {
|
|
var id = $(this).data('table');
|
|
// build text
|
|
var text = getExport(data, id);
|
|
$('#export-dlg').show();
|
|
$('#export_textarea').val(text).trigger('select');
|
|
document.execCommand('copy');
|
|
});
|
|
|
|
$('#export-dlg').click(function () {
|
|
$(this).hide();
|
|
});
|
|
|
|
$('.btn_import').button({
|
|
icons: {primary: 'ui-icon-circle-plus'},
|
|
text: false
|
|
})
|
|
.attr('title', _('Import from CSV'))
|
|
.css({width: 24, height: 24})
|
|
.click(function () {
|
|
$('#import-dlg').show().data('table', $(this).data('table'));
|
|
$('#import_textarea').val('').focus();
|
|
});
|
|
|
|
$('#import_button_ok').button({
|
|
icons: {primary: 'ui-icon-check'},
|
|
text: _('Export')
|
|
}).click(function () {
|
|
var $importDlg = $('#import-dlg');
|
|
getImport(data, $importDlg.data('table'), $('#import_textarea').val());
|
|
$importDlg.hide();
|
|
onchange();
|
|
});
|
|
$('#import_button_cancel').button({
|
|
icons: {primary: 'ui-icon-close'},
|
|
text: _('Close')
|
|
}).click(function () {
|
|
$('#import-dlg').hide();
|
|
});
|
|
|
|
$('.btn_delete_all').button({
|
|
icons: {primary: 'ui-icon-trash'},
|
|
text: false
|
|
})
|
|
.attr('title', _('Delete all entries'))
|
|
.css({width: 24, height: 24})
|
|
.click(function () {
|
|
if (window.confirm(_('All entries will be deleted. Are you sure?'))) {
|
|
var id = $(this).data('table');
|
|
if (data[id].length) {
|
|
data[id].splice(0, data[id].length);
|
|
$('#modbus_' + id).jsGrid('render');
|
|
onchange();
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
if (systemLang === 'cn') {
|
|
translate_cn();
|
|
}
|
|
|
|
if (typeof localStorage !== 'undefined') {
|
|
activePage = localStorage['modbuspage'];
|
|
$adapterContainer.tabs({active: parseInt(activePage || 0, 10)});
|
|
}
|
|
settings.params = settings.params || {};
|
|
|
|
var data = {
|
|
|
|
//添加自定义数据类型
|
|
config: settings.config || [],
|
|
yz: settings.yz || [],
|
|
dz: settings.dz || [],
|
|
power: settings.power || [],
|
|
video: settings.video || [],
|
|
ludeng: settings.ludeng || [],
|
|
dianti: settings.dianti || [],
|
|
|
|
params: {
|
|
bind: settings.params.bind || '192.168.0.1',
|
|
port: settings.params.port || 502,
|
|
deviceId: settings.params.deviceId || 0,
|
|
slave: settings.params.slave || 0,
|
|
recon: settings.params.recon || 60000,
|
|
poll: settings.params.poll || 1000,
|
|
pulsetime: settings.params.pulsetime || 1000,
|
|
round: settings.params.round || 2,
|
|
maxBlock: settings.params.maxBlock || 100,
|
|
maxBoolBlock: settings.params.maxBoolBlock || 128,
|
|
disInputsOffset: settings.params.disInputsOffset || 10001,
|
|
coilsOffset: settings.params.coilsOffset || 1,
|
|
inputRegsOffset: settings.params.inputRegsOffset || 30001,
|
|
holdingRegsOffset: settings.params.holdingRegsOffset || 40001,
|
|
showAliases: (settings.params.showAliases === undefined) ? true : settings.params.showAliases,
|
|
directAddresses: settings.params.directAddresses || false,
|
|
doNotRoundAddressToWord: settings.params.doNotRoundAddressToWord || false,
|
|
comName: settings.params.comName || '',
|
|
type: settings.params.type || 'tcp',
|
|
dataBits: settings.params.dataBits || 8,
|
|
stopBits: settings.params.stopBits || 1,
|
|
parity: settings.params.parity || 'none',
|
|
baudRate: settings.params.baudRate || 9600,
|
|
timeout: settings.params.timeout || 5000,
|
|
multiDeviceId: settings.params.multiDeviceId || false
|
|
}
|
|
};
|
|
data.params.showAliases = (data.params.showAliases === 'true' || data.params.showAliases === true);
|
|
data.params.directAddresses = (data.params.directAddresses === 'true' || data.params.directAddresses === true);
|
|
|
|
onChange = onchange;
|
|
|
|
$.each($('.modbus-params'), function () {
|
|
var id = $(this).attr('id');
|
|
if ($(this).attr('type') === 'checkbox') {
|
|
$(this).prop('checked', !!data.params[id.split('_')[1]]);
|
|
} else {
|
|
$(this).val(data.params[id.split('_')[1]]);
|
|
}
|
|
|
|
$(this).on('change', function () {
|
|
var id = $(this).attr('id').split('_')[1];
|
|
if (id === 'disInputsOffset') {
|
|
recalculate(data, 'disInputs', offsets.disInputs, parseInt($(this).val(), 10));
|
|
offsets.disInputs = parseInt($(this).val(), 10);
|
|
}
|
|
|
|
if (id === 'showAliases') {
|
|
switchAll(data);
|
|
}
|
|
|
|
onchange();
|
|
}).on('keyup', function () {
|
|
$(this).trigger('change');
|
|
});
|
|
});
|
|
|
|
isDirect = !!settings.params.directAddresses;
|
|
|
|
$('#modbus_directAddresses').on('change', function () {
|
|
isDirect = $(this).prop('checked');
|
|
});
|
|
|
|
|
|
settings.params.type = settings.params.type || 'tcp';
|
|
|
|
|
|
getIsAdapterAlive(function (isAlive) {
|
|
if (isAlive || common.enabled) {
|
|
getComPorts(settings.params.comName);
|
|
}
|
|
});
|
|
|
|
initTabs(onchange, data);
|
|
|
|
onchange(false);
|
|
}
|
|
|
|
function save(callback) {
|
|
|
|
var obj = {
|
|
params: {}
|
|
};
|
|
// finish editing
|
|
|
|
$.each($('.modbus-grid'), function () {
|
|
var id = $(this).attr('id');
|
|
var key = id.split('_')[1];
|
|
|
|
if ($(this).data('JSGrid')._editingRow) {
|
|
$(this).jsGrid('updateItem');
|
|
}
|
|
|
|
obj[key] = $(this).jsGrid('option', 'data');
|
|
});
|
|
|
|
$.each($('.modbus-params'), function () {
|
|
var id = $(this).attr('id').split('_')[1];
|
|
if ($(this).attr('type') === 'checkbox') {
|
|
obj.params[id] = $(this).prop('checked');
|
|
} else {
|
|
obj.params[id] = $(this).val();
|
|
}
|
|
});
|
|
callback(obj);
|
|
}
|
|
|
|
var _rmap = {
|
|
|
|
14: 1,
|
|
15: 0
|
|
};
|
|
var _dmap = {
|
|
0: 0,
|
|
1: 1,
|
|
2: 2,
|
|
3: 3,
|
|
4: 4,
|
|
5: 5,
|
|
6: 6,
|
|
7: 7,
|
|
8: 8,
|
|
9: 9,
|
|
10: 10,
|
|
11: 11,
|
|
12: 12,
|
|
13: 13,
|
|
14: 14,
|
|
15: 15
|
|
};
|
|
function address2alias(id, address, isDirect) {
|
|
var oldAddr = address;
|
|
if (typeof address === 'string') address = parseInt(address, 10);
|
|
if (typeof offsets[id] === 'string') offsets[id] = parseInt(offsets[id], 10);
|
|
address = parseInt(address, 10) || 0;
|
|
if (id === 'disInputs' || id === 'coils') {
|
|
address = Math.floor(address / 16) * 16 + (isDirect ? _dmap[address % 16] : _rmap[address % 16]);
|
|
address += offsets[id];
|
|
console.log('Convert addr: ' + oldAddr + ' => alias: ' + address);
|
|
return address
|
|
} else {
|
|
return address + offsets[id];
|
|
}
|
|
}
|
|
|
|
function alias2address(id, alias, isDirect) {
|
|
var oldAlias = alias;
|
|
if (typeof alias === 'string') alias = parseInt(alias, 10);
|
|
if (typeof offsets[id] === 'string') offsets[id] = parseInt(offsets[id], 10);
|
|
|
|
if (id === 'disInputs' || id === 'coils') {
|
|
alias = alias - offsets[id];
|
|
alias = Math.floor(alias / 16) * 16 + (isDirect ? _dmap[alias % 16] : _rmap[alias % 16]);
|
|
console.log('Convert alias: ' + oldAlias + ' => addr: ' + alias);
|
|
return alias;
|
|
} else {
|
|
return alias - offsets[id];
|
|
}
|
|
}
|
|
|
|
</script>
|
|
|
|
<!-- you have to put your config page in a div with id adapter-container -->
|
|
<div id="adapter-container" style="height: calc(100% - 40px);width: calc(100% - 10px); overflow: hidden;">
|
|
|
|
<ul>
|
|
<li><a href="#modbus_tab_g" class="translate">General</a></li>
|
|
<li><a href="#modbus_tab_config" class="translate">配置信息</a></li>
|
|
<li><a href="#modbus_tab_yz" class="translate">门禁</a></li>
|
|
<li><a href="#modbus_tab_dz" class="translate">车辆控制</a></li>
|
|
<li><a href="#modbus_tab_power" class="translate">能源控制</a></li>
|
|
<li><a href="#modbus_tab_video" class="translate">视频</a></li>
|
|
<li><a href="#modbus_tab_ludeng" class="translate">路灯</a></li>
|
|
<li><a href="#modbus_tab_dianti" class="translate">电梯</a></li>
|
|
|
|
<!--
|
|
<li><a href="#modbus_tab_coils" class="translate">Coils</a></li>
|
|
-->
|
|
</ul>
|
|
|
|
<div id="modbus_tab_g" style="display: flex; align-items: center; flex-direction: column;overflow: auto" class="modbus-tab">
|
|
<div class="logo">智慧园区配置信息</div>
|
|
<img src="img/plc_back.png" class="back_image">
|
|
|
|
|
|
</div>
|
|
<div id="modbus_tab_config" class="modbus-tab">
|
|
<div class="table_head_btn" data-grid="modbus_config">
|
|
<button class="btn_delete_all translateB" data-table="config"></button>
|
|
<button class="btn_export translateB" data-table="config"></button>
|
|
<button class="btn_import translateB" data-table="config"></button>
|
|
</div>
|
|
<div id="modbus_config" class="modbus-grid"></div>
|
|
</div>
|
|
<div id="modbus_tab_yz" class="modbus-tab">
|
|
<div class="table_head_btn" data-grid="modbus_yz">
|
|
<button class="btn_delete_all translateB" data-table="yz"></button>
|
|
<button class="btn_export translateB" data-table="yz"></button>
|
|
<button class="btn_import translateB" data-table="yz"></button>
|
|
</div>
|
|
<div id="modbus_yz" class="modbus-grid"></div>
|
|
</div>
|
|
|
|
<div id="modbus_tab_dz" class="modbus-tab">
|
|
<div class="table_head_btn" data-grid="modbus_dz">
|
|
<button class="btn_delete_all translateB" data-table="dz"></button>
|
|
<button class="btn_export translateB" data-table="dz"></button>
|
|
<button class="btn_import translateB" data-table="dz"></button>
|
|
</div>
|
|
<div id="modbus_dz" class="modbus-grid"></div>
|
|
</div>
|
|
|
|
<div id="modbus_tab_power" class="modbus-tab">
|
|
<div class="table_head_btn" data-grid="modbus_power">
|
|
<button class="btn_delete_all translateB" data-table="power"></button>
|
|
<button class="btn_export translateB" data-table="power"></button>
|
|
<button class="btn_import translateB" data-table="power"></button>
|
|
</div>
|
|
<div id="modbus_power" class="modbus-grid"></div>
|
|
</div>
|
|
|
|
<div id="modbus_tab_video" class="modbus-tab">
|
|
<div class="table_head_btn" data-grid="modbus_video">
|
|
<button class="btn_delete_all translateB" data-table="video"></button>
|
|
<button class="btn_export translateB" data-table="video"></button>
|
|
<button class="btn_import translateB" data-table="video"></button>
|
|
</div>
|
|
<div id="modbus_video" class="modbus-grid"></div>
|
|
</div>
|
|
|
|
<div id="modbus_tab_ludeng" class="modbus-tab">
|
|
<div class="table_head_btn" data-grid="modbus_ludeng">
|
|
<button class="btn_delete_all translateB" data-table="ludeng"></button>
|
|
<button class="btn_export translateB" data-table="ludeng"></button>
|
|
<button class="btn_import translateB" data-table="ludeng"></button>
|
|
</div>
|
|
<div id="modbus_ludeng" class="modbus-grid"></div>
|
|
</div>
|
|
|
|
<div id="modbus_tab_dianti" class="modbus-tab">
|
|
<div class="table_head_btn" data-grid="modbus_dianti">
|
|
<button class="btn_delete_all translateB" data-table="dianti"></button>
|
|
<button class="btn_export translateB" data-table="dianti"></button>
|
|
<button class="btn_import translateB" data-table="dianti"></button>
|
|
</div>
|
|
<div id="modbus_dianti" class="modbus-grid"></div>
|
|
</div>
|
|
|
|
<div id="modbus_tab_dis_inputs" class="modbus-tab">
|
|
<div class="table_head_btn" data-grid="modbus_disInputs">
|
|
<div class="offsets"><span class="translate">Start address:</span><input type="text" maxsize="6" class="modbus-params" id="modbus_disInputsOffset" size="6"/></div>
|
|
<button class="btn_delete_all translateB" data-table="disInputs"></button>
|
|
<button class="btn_export translateB" data-table="disInputs"></button>
|
|
<button class="btn_import translateB" data-table="disInputs"></button>
|
|
</div>
|
|
<div id="modbus_disInputs" class="modbus-grid"></div>
|
|
</div>
|
|
|
|
<div id="modbus_tab_coils" class="modbus-tab">
|
|
<div class="table_head_btn" data-grid="modbus_coils">
|
|
<div class="offsets"><span class="translate">Start address:</span><input type="text" maxsize="6" class="modbus-params" id="modbus_coilsOffset" size="6"/></div>
|
|
<button class="btn_delete_all translateB" data-table="coils"></button>
|
|
<button class="btn_export translateB" data-table="coils"></button>
|
|
<button class="btn_import translateB" data-table="coils"></button>
|
|
<button class="btn_toggle_pool translateB" title="Polling">Toggle poll</button>
|
|
<button class="btn_toggle_wp translateB" title="write as Pulse">Toggle WP</button>
|
|
</div>
|
|
<div id="modbus_coils" class="modbus-grid"></div>
|
|
</div>
|
|
<div id="modbus_tab_input_regs" class="modbus-tab">
|
|
<div class="table_head_btn" data-grid="modbus_inputRegs">
|
|
<div class="offsets"><span class="translate">Start address:</span><input type="text" maxsize="6" class="modbus-params" id="modbus_inputRegsOffset" size="6"/></div>
|
|
<button class="btn_delete_all translateB" data-table="inputRegs"></button>
|
|
<button class="btn_export translateB" data-table="inputRegs"></button>
|
|
<button class="btn_import translateB" data-table="inputRegs"></button>
|
|
</div>
|
|
<div id="modbus_inputRegs" class="modbus-grid"></div>
|
|
</div>
|
|
<div id="modbus_tab_holding_regs" class="modbus-tab">
|
|
<div class="table_head_btn" data-grid="modbus_holdingRegs">
|
|
<div class="offsets"><span class="translate">Start address:</span><input type="text" maxsize="6" class="modbus-params" id="modbus_holdingRegsOffset" size="6"/></div>
|
|
<button class="btn_delete_all translateB" data-table="holdingRegs"></button>
|
|
<button class="btn_export translateB" data-table="holdingRegs"></button>
|
|
<button class="btn_import translateB" data-table="holdingRegs"></button>
|
|
<button class="btn_toggle_pool translateB" title="Polling">Toggle poll</button>
|
|
<!--button class="btn_toggle_wp translateB" title="write as Pulse">Toggle WP</button-->
|
|
</div>
|
|
<div id="modbus_holdingRegs" class="modbus-grid"></div>
|
|
</div>
|
|
<div id="export-dlg" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: none; z-index: 100; background: white">
|
|
<div id="export_help" class="translate" style="position: absolute; opacity: 0.8; top: 10px; right: 10px; font-size: 24px; font-weight: bold; color: blue">Text copied to clipboard. Click to close the window</div>
|
|
<textarea id="export_textarea" readonly style="resize: none; width: 100%; height: calc(100% - 40px); margin-top: 40px;"></textarea>
|
|
</div>
|
|
<div id="import-dlg" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: none; z-index: 100; background: white">
|
|
<textarea id="import_textarea" style="width: 100%; height: calc(100% - 40px); resize: none;"></textarea>
|
|
<button id="import_button_ok" style="position: absolute; bottom: 10px; right: 120px;" ></button>
|
|
<button id="import_button_cancel" style="position: absolute; bottom: 10px; right: 10px;"></button>
|
|
</div>
|
|
<div id="delete-dlg" style="display: none;">
|
|
<p>
|
|
<span class="ui-icon ui-icon-alert" style="float:left; margin:12px 12px 20px 0;"></span>
|
|
<span class="translate">Are you sure?</span><br><br>
|
|
<input type="checkbox" id="delete_ignore_dialog" /><label class="translate">Say "yes" for the next minute:</label>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
</html>
|