2019-01-16 12:40:58 +08:00
|
|
|
<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-de.js"></script>
|
|
|
|
<script type="text/javascript" src="./lib/js/grid.locale-ru.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>
|
|
|
|
<style>
|
|
|
|
.dialog-config {
|
|
|
|
overflow: hidden !important;
|
|
|
|
}
|
|
|
|
|
|
|
|
.ui-tabs-panel {
|
|
|
|
height: calc(100% - 70px);
|
|
|
|
padding: 0 !important;
|
|
|
|
}
|
|
|
|
|
|
|
|
.table_header {
|
|
|
|
background-color: blue;
|
|
|
|
color: white;
|
|
|
|
}
|
|
|
|
|
|
|
|
.bind {
|
|
|
|
width: 150px;
|
|
|
|
text-align: right;
|
|
|
|
}
|
|
|
|
|
|
|
|
.ui-jqgrid-titlebar {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
|
|
|
|
.ui-jqgrid-bdiv {
|
|
|
|
overflow-x: hidden !important;
|
|
|
|
}
|
|
|
|
|
|
|
|
.ui-button-text-only .ui-button-text {
|
|
|
|
padding: .3em !important;
|
|
|
|
}
|
|
|
|
|
|
|
|
.modbus-tab {
|
|
|
|
/*overflow: hidden;*/
|
|
|
|
position: relative;
|
|
|
|
height: calc(100% - 20px);
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
|
|
|
|
.modbus-grid {
|
|
|
|
height: 100% !important;
|
|
|
|
width: 100% !important;
|
|
|
|
}
|
|
|
|
|
|
|
|
.jsgrid-grid-body {
|
|
|
|
height: calc(100% - 58px) !important;
|
|
|
|
}
|
|
|
|
|
|
|
|
.jsgrid-table {
|
|
|
|
width: 100% !important;
|
|
|
|
font-size: 1em;
|
|
|
|
}
|
|
|
|
|
|
|
|
.jsgrid-insert-mode-button {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*.jsgrid-edit-row input {
|
|
|
|
padding: 0;
|
|
|
|
}*/
|
|
|
|
.jsgrid-table td {
|
|
|
|
padding: 0.2em 0.2em !important;
|
|
|
|
}
|
|
|
|
|
|
|
|
.table_head_btn {
|
|
|
|
display: inline-flex;
|
|
|
|
text-align: center;
|
|
|
|
font-size: 1.1em;
|
|
|
|
position: absolute;
|
|
|
|
z-index: 99;
|
|
|
|
right: 5px;
|
|
|
|
top: -27px;
|
|
|
|
color: white;
|
|
|
|
}
|
|
|
|
|
|
|
|
.back_image {
|
|
|
|
position: absolute;
|
|
|
|
top: 0;
|
|
|
|
left: 0;
|
|
|
|
height: 100%;
|
|
|
|
width: 100%;
|
|
|
|
z-index: 0;
|
|
|
|
opacity: 0.3;
|
|
|
|
}
|
|
|
|
|
|
|
|
.logo {
|
|
|
|
position: absolute;
|
|
|
|
top: 0;
|
|
|
|
left: 0;
|
|
|
|
z-index: 1;
|
|
|
|
color: rgb(0, 153, 153);
|
|
|
|
font-weight: bolder;
|
|
|
|
font-size: 39px;
|
|
|
|
padding: 9px;
|
|
|
|
font-family: sans-serif;
|
|
|
|
}
|
|
|
|
|
|
|
|
tr td {
|
|
|
|
padding-left: 10px;
|
|
|
|
}
|
|
|
|
#adapter-container {
|
|
|
|
-webkit-touch-callout: none;
|
|
|
|
-webkit-user-select: none;
|
|
|
|
-khtml-user-select: none;
|
|
|
|
-moz-user-select: none;
|
|
|
|
-ms-user-select: none;
|
|
|
|
-webkit-user-drag: none;
|
|
|
|
user-select: none;
|
|
|
|
}
|
|
|
|
|
|
|
|
#export-dlg .select-dropdown {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
#export-dlg .dropdown-content {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
#export-dlg .caret {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
|
|
|
|
<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,
|
|
|
|
'stringle': 0
|
|
|
|
};
|
|
|
|
|
|
|
|
var attempts = 0;
|
|
|
|
var ignoreDialog = 0;
|
|
|
|
|
|
|
|
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;
|
|
|
|
if (isAliases) {
|
|
|
|
obj.address = alias2address(id, obj._address);
|
|
|
|
} else {
|
|
|
|
obj.address = obj._address;
|
|
|
|
}
|
|
|
|
} else if (mapping[m] === 'factor') {
|
|
|
|
obj.factor = parseFloat(val) || 1;
|
|
|
|
} else if (mapping[m] === 'offset') {
|
|
|
|
obj.offset = parseFloat(val) || 0;
|
|
|
|
} else if (mapping[m] === 'len') {
|
|
|
|
obj.len = parseInt(val, 10) || 1;
|
|
|
|
} else if (mapping[m] === 'poll') {
|
|
|
|
obj[mapping[m]] = val || '';
|
|
|
|
obj.poll = (obj.poll.toLowerCase() === 'true' || obj.poll === '1' || obj.poll === '+');
|
|
|
|
} else if (mapping[m] === 'wp') {
|
|
|
|
obj[mapping[m]] = val || '';
|
|
|
|
obj.wp = (obj.wp.toLowerCase() === 'true' || obj.wp === '1' || obj.wp === '+');
|
|
|
|
} else if (mapping[m] === 'cw') {
|
|
|
|
obj[mapping[m]] = val || '';
|
|
|
|
obj.cw = (obj.cw.toLowerCase() === 'true' || obj.cw === '1' || obj.cw === '+');
|
|
|
|
} 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, '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: 'switch', text: 'switch'},
|
|
|
|
{value: 'button', text: 'button'},
|
2019-01-16 12:57:19 +08:00
|
|
|
{value: 'indicator', text: 'indicator'}
|
2019-01-16 12:40:58 +08:00
|
|
|
];
|
|
|
|
|
|
|
|
var typeItems = [
|
|
|
|
{value: '', text: ''},
|
2019-01-16 12:57:19 +08:00
|
|
|
{value: 'int8le', text: 'Signed 8 bit (Little Endian)'}
|
2019-01-16 12:40:58 +08:00
|
|
|
];
|
|
|
|
|
|
|
|
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: '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'},
|
|
|
|
{name: 'cw' , title: _('CW'), type: 'checkbox', width: '35px'},
|
|
|
|
{ type: 'control', width: '80px'}
|
|
|
|
];
|
|
|
|
|
|
|
|
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')) {
|
|
|
|
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 === 'de') {
|
|
|
|
translate_de();
|
2019-01-16 12:57:19 +08:00
|
|
|
}
|
2019-01-16 12:40:58 +08:00
|
|
|
|
|
|
|
if (typeof localStorage !== 'undefined') {
|
|
|
|
activePage = localStorage['modbuspage'];
|
|
|
|
$adapterContainer.tabs({active: parseInt(activePage || 0, 10)});
|
|
|
|
}
|
|
|
|
settings.params = settings.params || {};
|
|
|
|
|
|
|
|
var data = {
|
|
|
|
disInputs: settings.disInputs || [],
|
|
|
|
coils: settings.coils || [],
|
|
|
|
inputRegs: settings.inputRegs || [],
|
|
|
|
holdingRegs: settings.holdingRegs || [],
|
|
|
|
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,
|
|
|
|
alwaysUpdate: settings.params.alwaysUpdate || 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);
|
|
|
|
data.params.alwaysUpdate = (data.params.alwaysUpdate === 'true' || data.params.alwaysUpdate === 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 === 'coilsOffset') {
|
|
|
|
recalculate(data, 'coils', offsets.coils, parseInt($(this).val(), 10));
|
|
|
|
offsets.coils = parseInt($(this).val(), 10);
|
|
|
|
}
|
|
|
|
if (id === 'inputRegsOffset') {
|
|
|
|
recalculate(data, 'inputRegs', offsets.inputRegs, parseInt($(this).val(), 10));
|
|
|
|
offsets.inputRegs = parseInt($(this).val(), 10);
|
|
|
|
}
|
|
|
|
if (id === 'holdingRegsOffset') {
|
|
|
|
recalculate(data, 'holdingRegs', offsets.holdingRegs, parseInt($(this).val(), 10));
|
|
|
|
offsets.holdingRegs = 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');
|
|
|
|
});
|
|
|
|
|
|
|
|
$('#modbus_showAliases').on('change', function () {
|
|
|
|
if (!$(this).prop('checked')) {
|
|
|
|
$('#modbus_directAddresses').prop('checked', false).prop('disabled', true);
|
|
|
|
} else {
|
|
|
|
$('#modbus_directAddresses').prop('disabled', false);
|
|
|
|
}
|
|
|
|
}).trigger('change');
|
|
|
|
|
|
|
|
settings.params.type = settings.params.type || 'tcp';
|
|
|
|
|
|
|
|
$('#modbus_type').on('change', function () {
|
|
|
|
if ($(this).val() === 'tcp' || $(this).val() === 'tcprtu') {
|
|
|
|
$('.tcp').show();
|
|
|
|
$('.serial').hide();
|
|
|
|
if ($(this).val() === 'tcprtu') {
|
|
|
|
$('#modbus_slave').val(0).prop('disabled', true).trigger('change');
|
|
|
|
} else {
|
|
|
|
$('#modbus_slave').prop('disabled', false);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$('.tcp').hide();
|
|
|
|
$('.serial').show();
|
|
|
|
$('#modbus_slave').val(0).prop('disabled', true).trigger('change');
|
|
|
|
}
|
|
|
|
initTabs(onchange);
|
|
|
|
}).trigger('change');
|
|
|
|
|
|
|
|
$('#modbus_slave').on('change', function () {
|
|
|
|
if ($(this).val() === '0') {
|
|
|
|
$('#multiDeviceId').show();
|
|
|
|
} else {
|
|
|
|
$('#multiDeviceId').hide();
|
|
|
|
$('#modbus_multiDeviceId').prop('checked', false);
|
|
|
|
}
|
|
|
|
initTabs(onchange);
|
|
|
|
}).trigger('change');
|
|
|
|
|
|
|
|
$('#multiDeviceId').on('change', function () {
|
|
|
|
initTabs(onchange);
|
|
|
|
});
|
|
|
|
|
|
|
|
getIsAdapterAlive(function (isAlive) {
|
|
|
|
if (isAlive || common.enabled) {
|
2019-01-16 13:13:47 +08:00
|
|
|
//
|
2019-01-16 12:40:58 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
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 = {
|
|
|
|
0: 15,
|
|
|
|
1: 14,
|
|
|
|
2: 13,
|
|
|
|
3: 12,
|
|
|
|
4: 11,
|
|
|
|
5: 10,
|
|
|
|
6: 9,
|
|
|
|
7: 8,
|
|
|
|
8: 7,
|
|
|
|
9: 6,
|
|
|
|
10: 5,
|
|
|
|
11: 4,
|
|
|
|
12: 3,
|
|
|
|
13: 2,
|
|
|
|
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_holding_regs">Holding Registers</a></li>
|
|
|
|
</ul>
|
|
|
|
<div id="modbus_tab_g" style="display: flex; align-items: center; flex-direction: column;overflow: auto" class="modbus-tab">
|
2019-01-16 12:47:45 +08:00
|
|
|
<div class="logo">串口开关适配器</div>
|
2019-01-16 12:40:58 +08:00
|
|
|
<img src="img/plc_back.png" class="back_image">
|
|
|
|
|
|
|
|
<table class="ui-widget-content" style="z-index: 2;margin-top: 20px; border-collapse: collapse; display: inline; border: 1px solid black;">
|
|
|
|
<tr>
|
|
|
|
<td style="text-align: center" colspan="3" class="ui-widget-header translate">General</td>
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
<tr>
|
|
|
|
<td><label class="translate" for="modbus_showAliases">Use aliases as address:</label></td>
|
|
|
|
<td><input style="margin-right: 5px;text-align: right" class="modbus-params" type="checkbox" id="modbus_showAliases"/></td>
|
|
|
|
<td></td>
|
|
|
|
</tr>
|
|
|
|
<tr class="direct-addresses">
|
|
|
|
<td><label class="translate" for="modbus_directAddresses">Use direct addresses by aliases:</label></td>
|
|
|
|
<td><input style="margin-right: 5px;text-align: right" class="modbus-params" type="checkbox" id="modbus_directAddresses"/></td>
|
|
|
|
<td></td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><label class="translate" for="modbus_doNotRoundAddressToWord">Do not align addresses to word:</label></td>
|
|
|
|
<td><input style="margin-right: 5px; text-align: right" class="modbus-params" type="checkbox" id="modbus_doNotRoundAddressToWord"/></td>
|
|
|
|
<td></td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td style="width: 184px"><label class="translate" for="modbus_round">Round Real to:</label></td>
|
|
|
|
<td style="text-align: center"><input style="margin-right: 5px; text-align: right" type="text" class="modbus-params" id="modbus_round"></td>
|
|
|
|
<td></td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><label class="translate" for="modbus_poll">Poll delay:</label></td>
|
|
|
|
<td style="text-align: center"><input style="margin-right: 5px;text-align: right" class="modbus-params" id="modbus_poll"/></td>
|
|
|
|
<td style="padding-right: 20px">ms</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><label class="translate" for="modbus_recon">Reconnect time:</label></td>
|
|
|
|
<td style="text-align: center"><input style="margin-right: 5px;text-align: right" type="text" class="modbus-params" id="modbus_recon"></td>
|
|
|
|
<td>ms</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><label for="modbus_timeout" class="translate">Read timeout:</label></td>
|
|
|
|
<td style="text-align: center"><input style="margin-right: 5px;text-align: right" type="text" class="modbus-params" id="modbus_timeout"></td>
|
|
|
|
<td>ms</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><label class="translate" for="modbus_pulsetime">Pulse time:</label></td>
|
|
|
|
<td style="text-align: center"><input style="margin-right: 5px;text-align: right" type="text" class="modbus-params" id="modbus_pulsetime"></td>
|
|
|
|
<td>ms</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><label class="translate" for="modbus_maxBlock">Max read request length:</label></td>
|
|
|
|
<td style="text-align: center"><input style="margin-right: 5px;text-align: right" type="text" class="modbus-params" id="modbus_maxBlock"></td>
|
|
|
|
<td class="translate">registers</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><label class="translate" for="modbus_maxBoolBlock">Max read request length (booleans):</label></td>
|
|
|
|
<td style="text-align: center"><input style="margin-right: 5px;text-align: right" type="text" class="modbus-params" id="modbus_maxBoolBlock"></td>
|
|
|
|
<td class="translate">registers</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><label class="translate" for="modbus_alwaysUpdate">Update unchanged states:</label></td>
|
|
|
|
<td><input style="margin-right: 5px;text-align: right" class="modbus-params" type="checkbox" id="modbus_alwaysUpdate"/></td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td colspan="3" style="height: 10px"></td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
<div id="modbus_tab_holding_regs" class="modbus-tab">
|
|
|
|
<div class="table_head_btn" data-grid="modbus_holdingRegs">
|
|
|
|
<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>
|
2019-01-16 12:44:36 +08:00
|
|
|
<!--button class="btn_toggle_pool translateB" title="Polling">Toggle poll</button-->
|
2019-01-16 12:40:58 +08:00
|
|
|
<!--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>
|