mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-07 20:54:14 +08:00
🌴 Sync 2026-03-05 23:51:42
This commit is contained in:
1 parent
97c049ed0a
commit
0acff03804
14253 files changed
+3893239
No files matched your search
Binary file not shown.
|
After Width: | Height: | Size: 9.0 KiB |
@@ -0,0 +1,637 @@
|
||||
'use strict';
|
||||
'require dom';
|
||||
'require form';
|
||||
'require fs';
|
||||
'require ui';
|
||||
'require uci';
|
||||
'require view';
|
||||
|
||||
/*
|
||||
Copyright 2022-2025 Rafał Wabik - IceG - From eko.one.pl forum
|
||||
|
||||
Licensed to the GNU General Public License v3.0.
|
||||
*/
|
||||
|
||||
document.head.append(E('style', {'type': 'text/css'},
|
||||
`
|
||||
#smsTable {
|
||||
width: 100%;
|
||||
border: 1px solid var(--border-color-medium) !important;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 10px;
|
||||
text-align: justify !important;
|
||||
vertical-align: top !important;
|
||||
}
|
||||
|
||||
td input[type="checkbox"] {
|
||||
float: left !important;
|
||||
margin: 0 auto !important;
|
||||
width: 17px !important;
|
||||
}
|
||||
|
||||
#smsTable tr:nth-child(odd) td{
|
||||
background: var(--background-color-medium) !important;
|
||||
border-bottom: 1px solid var(--border-color-medium) !important;
|
||||
border-top: 1px solid var(--border-color-medium) !important;
|
||||
}
|
||||
|
||||
#smsTable tr:nth-child(even) td{
|
||||
border-bottom: 1px solid var(--border-color-medium) !important;
|
||||
border-top: 1px solid var(--border-color-medium) !important;
|
||||
}
|
||||
|
||||
#smsTable .checker {
|
||||
width: 7% !important;
|
||||
}
|
||||
|
||||
#smsTable .from {
|
||||
width: 11% !important;
|
||||
}
|
||||
|
||||
#smsTable .received {
|
||||
width: 15% !important;
|
||||
}
|
||||
|
||||
#smsTable .message {
|
||||
width: 88% !important;
|
||||
}
|
||||
`));
|
||||
|
||||
function msg_bar(v, m) {
|
||||
var pg = document.querySelector('#msg')
|
||||
var vn = parseInt(v) || 0;
|
||||
var mn = parseInt(m) || 100;
|
||||
var pc = Math.floor((100 / mn) * vn);
|
||||
|
||||
pg.firstElementChild.style.width = pc + '%';
|
||||
pg.setAttribute('title', '%s'.format(v) + ' / ' + '%s'.format(m) + ' ('+ pc + '%)');
|
||||
}
|
||||
|
||||
|
||||
function save_count() {
|
||||
uci.load('sms_tool_js').then(function() {
|
||||
|
||||
var storeL = (uci.get('sms_tool_js', '@sms_tool_js[0]', 'storage'));
|
||||
var portR = (uci.get('sms_tool_js', '@sms_tool_js[0]', 'readport'));
|
||||
|
||||
L.resolveDefault(fs.exec_direct('/usr/bin/sms_tool', [ '-s' , storeL , '-d' , portR , 'status' ]))
|
||||
.then(function(res) {
|
||||
if (res) {
|
||||
var total = res.substring(res.indexOf("total"));
|
||||
var t = total.replace ( /[^\d.]/g, '' );
|
||||
var used = res.substring(17, res.indexOf("total"));
|
||||
var u = used.replace ( /[^\d.]/g, '' );
|
||||
uci.set('sms_tool_js', '@sms_tool_js[0]', 'sms_count', L.toArray(u).join(' '));
|
||||
uci.save();
|
||||
uci.apply();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
uci.load('sms_tool_js');
|
||||
},
|
||||
|
||||
handleSWarea: function(ev) {
|
||||
switch (document.querySelector('input[name="filter_area"]:checked').value) {
|
||||
case 'sim':
|
||||
uci.set('sms_tool_js', '@sms_tool_js[0]', 'storage', "SM");
|
||||
uci.save();
|
||||
uci.apply();
|
||||
break;
|
||||
case 'memory':
|
||||
uci.set('sms_tool_js', '@sms_tool_js[0]', 'storage', "ME");
|
||||
uci.save();
|
||||
uci.apply();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
handleDelete: function(ev) {
|
||||
if (document.querySelectorAll('input[name="smsn"]:checked').length == 0){
|
||||
ui.addNotification(null, E('p', _('Please select the message(s) to be deleted')), 'info');
|
||||
}
|
||||
else {
|
||||
if (document.querySelectorAll('input[name="smsn"]:checked').length === document.querySelectorAll('input[name="smsn"]').length) {
|
||||
if (confirm(_('Delete all the messages?')))
|
||||
{
|
||||
var sections = uci.sections('sms_tool_js');
|
||||
var portDA = sections[0].readport;
|
||||
var storeDA = sections[0].storage;
|
||||
|
||||
fs.exec_direct('/usr/bin/sms_tool', [ '-d' , portDA , 'delete' , 'all' ]);
|
||||
document.getElementById("ch-all").checked = false;
|
||||
|
||||
var rowCount = smsTable.rows.length;
|
||||
for (var i = rowCount - 1; i > 0; i--) {
|
||||
smsTable.deleteRow(i);}
|
||||
setTimeout(function() {
|
||||
L.resolveDefault(fs.exec_direct('/usr/bin/sms_tool', [ '-s' , storeDA , '-d' , portDA , 'status' ]))
|
||||
.then(function(res) {
|
||||
if (res) {
|
||||
var total = res.substring(res.indexOf("total"));
|
||||
var t = total.replace ( /[^\d.]/g, '' );
|
||||
var u = "0";
|
||||
msg_bar(Math.floor(u), t);
|
||||
save_count();
|
||||
}
|
||||
});
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if (confirm(_('Delete selected message(s)?')))
|
||||
{
|
||||
uci.load('sms_tool_js').then(function() {
|
||||
|
||||
var storeL = (uci.get('sms_tool_js', '@sms_tool_js[0]', 'storage'));
|
||||
var portR = (uci.get('sms_tool_js', '@sms_tool_js[0]', 'readport'));
|
||||
|
||||
var array = [];
|
||||
var checkb = document.querySelectorAll('input[type=checkbox]:checked');
|
||||
|
||||
for (var i = 0; i < checkb.length; i++) {
|
||||
if (checkb[i] != source)
|
||||
array.push(checkb[i].id)
|
||||
}
|
||||
|
||||
if (array) {
|
||||
|
||||
var args = [];
|
||||
var sections = uci.sections('sms_tool_js');
|
||||
var portDEL = sections[0].readport;
|
||||
var storeDS = sections[0].storage;
|
||||
|
||||
args.push(array);
|
||||
var ax = args.toString();
|
||||
ax = ax.replace(/,/g, ' ');
|
||||
ax = ax.replace(/-/g, ' ');
|
||||
|
||||
var smsnr = ax.split(" ");
|
||||
|
||||
var smsallchars = smsnr.toString();
|
||||
var smsdelcount = 0;
|
||||
var smsdeleted = 0;
|
||||
|
||||
var inumber = false;
|
||||
|
||||
for (var i = 0; i < smsallchars.length; i++) {
|
||||
var ch = smsallchars[i];
|
||||
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
if (!inumber) {
|
||||
smsdelcount++;
|
||||
inumber = true;
|
||||
}
|
||||
} else if (ch === ',') {
|
||||
inumber = false;
|
||||
} else {
|
||||
inumber = false;
|
||||
}
|
||||
}
|
||||
|
||||
var deletelabel = document.getElementById("deleteinfo");
|
||||
deletelabel.style.display = 'block';
|
||||
|
||||
for (var i=0; i < smsnr.length + 2; i++)
|
||||
{
|
||||
(function(i) {
|
||||
setTimeout(function() {
|
||||
smsnr[i] = parseInt(smsnr[i], 10);
|
||||
|
||||
if (!Number.isNaN(smsnr[i]))
|
||||
{
|
||||
fs.exec_direct('/usr/bin/sms_tool', [ '-d' , portDEL , 'delete' , smsnr[i] ]);
|
||||
smsdeleted++;
|
||||
L.resolveDefault(fs.exec_direct('/usr/bin/sms_tool', [ '-s' , storeL , '-d' , portR , 'status' ]))
|
||||
.then(function(res) {
|
||||
if (res) {
|
||||
var total = res.substring(res.indexOf("total"));
|
||||
var t = total.replace ( /[^\d.]/g, '' );
|
||||
var used = res.substring(17, res.indexOf("total"));
|
||||
var u = used.replace ( /[^\d.]/g, '' );
|
||||
msg_bar(Math.floor(u), t);
|
||||
deletelabel.innerHTML = _('Please wait... deleted')+' '+smsdeleted+' '+_('of')+' '+smsdelcount+' '+_('selected messages');
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
L.resolveDefault(fs.exec_direct('/usr/bin/sms_tool', [ '-s' , storeL , '-d' , portR , 'status' ]))
|
||||
.then(function(res) {
|
||||
if (res) {
|
||||
var total = res.substring(res.indexOf("total"));
|
||||
var t = total.replace ( /[^\d.]/g, '' );
|
||||
var used = res.substring(17, res.indexOf("total"));
|
||||
var u = used.replace ( /[^\d.]/g, '' );
|
||||
msg_bar(Math.floor(u), t);
|
||||
deletelabel.innerHTML = _('Please wait... deleted')+' '+smsdeleted+' '+_('of')+' '+smsdelcount+' '+_('selected messages');
|
||||
}
|
||||
});
|
||||
|
||||
if (smsdelcount == smsdeleted) {
|
||||
setTimeout(function() {
|
||||
var hidecount = document.getElementById('deleteinfo');
|
||||
hidecount.style.display = 'none';
|
||||
save_count();
|
||||
}, 7000);
|
||||
}
|
||||
}, 1500 * i);
|
||||
})(i);
|
||||
L.resolveDefault(fs.exec_direct('/usr/bin/sms_tool', [ '-s' , storeL , '-d' , portR , 'status' ]))
|
||||
.then(function(res) {
|
||||
if (res) {
|
||||
var total = res.substring(res.indexOf("total"));
|
||||
var t = total.replace ( /[^\d.]/g, '' );
|
||||
var used = res.substring(17, res.indexOf("total"));
|
||||
var u = used.replace ( /[^\d.]/g, '' );
|
||||
msg_bar(Math.floor(u), t);
|
||||
deletelabel.innerHTML = _('Please wait... deleted')+' '+smsdeleted+' '+_('of')+' '+smsdelcount+' '+_('selected messages');
|
||||
}
|
||||
});
|
||||
}
|
||||
var table = document.getElementById("smsTable");
|
||||
var index = 1;
|
||||
while (index < table.rows.length) {
|
||||
var input = table.rows[index].cells[0].children[0];
|
||||
if (input && input.checked) {
|
||||
table.deleteRow(index);
|
||||
}
|
||||
else {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
handleRefresh: function(ev) {
|
||||
window.location.reload();
|
||||
},
|
||||
|
||||
|
||||
handleSelect: function(ev) {
|
||||
var checkBox = document.getElementById("ch-all");
|
||||
var checkBoxes = document.querySelectorAll('input[type="checkbox"]');
|
||||
|
||||
if (checkBox.checked == true){
|
||||
for (var i = 0; i < checkBoxes.length; i++)
|
||||
checkBoxes[i].setAttribute('checked', 'true');
|
||||
} else {
|
||||
for (var i = 0; i < checkBoxes.length; i++)
|
||||
checkBoxes[i].removeAttribute('checked');
|
||||
}
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
|
||||
var sections, store;
|
||||
var view = document.getElementById("smssarea");
|
||||
store = '-';
|
||||
|
||||
uci.load('sms_tool_js').then(function() {
|
||||
var storeL = (uci.get('sms_tool_js', '@sms_tool_js[0]', 'storage'));
|
||||
var portR = (uci.get('sms_tool_js', '@sms_tool_js[0]', 'readport'));
|
||||
var smsM = (uci.get('sms_tool_js', '@sms_tool_js[0]', 'mergesms'));
|
||||
var algo = (uci.get('sms_tool_js', '@sms_tool_js[0]', 'algorithm'));
|
||||
var hide = (uci.get('sms_tool_js', '@sms_tool_js[0]', 'bnumber'));
|
||||
var ledn = (uci.get('sms_tool_js', '@sms_tool_js[0]', 'lednotify'));
|
||||
var ledt = (uci.get('sms_tool_js', '@sms_tool_js[0]', 'ledtype'));
|
||||
var direct = (uci.get('sms_tool_js', '@sms_tool_js[0]', 'direction'));
|
||||
|
||||
if (!portR) {
|
||||
ui.addNotification(null, E('p', _('The package requires user configuration. \
|
||||
<br /><br /><b>The following need to be set:</b> \
|
||||
<ul><li>1. All ports for communication with the modem.</li><li>2. Additional options specific to the given modem (for handling USSD codes).</li><li> \
|
||||
3. Notification LED (optional).</li><li><ul>')), 'info');
|
||||
}
|
||||
|
||||
var sections = uci.sections('sms_tool_js');
|
||||
var led = sections[0].smsled;
|
||||
|
||||
if (storeL == "SM")
|
||||
document.querySelector('input[name="filter_area"][value="sim"]').checked = true;
|
||||
if (storeL == "ME")
|
||||
document.querySelector('input[name="filter_area"][value="memory"]').checked = true;
|
||||
if (ledn == "1")
|
||||
{
|
||||
switch (ledt) {
|
||||
case 'S':
|
||||
fs.exec_direct('/etc/init.d/led', [ 'restart' ]);
|
||||
break;
|
||||
case 'D':
|
||||
fs.write('/sys/class/leds/'+led+'/brightness', '0');
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
L.resolveDefault(fs.exec_direct('/usr/bin/sms_tool', [ '-s' , storeL , '-d' , portR , 'status' ]))
|
||||
.then(function(res) {
|
||||
if (res) {
|
||||
var total = res.substring(res.indexOf("total"));
|
||||
var t = total.replace ( /[^\d.]/g, '' );
|
||||
|
||||
var used = res.substring(17, res.indexOf("total"));
|
||||
var u = used.replace ( /[^\d.]/g, '' );
|
||||
|
||||
L.resolveDefault(fs.exec_direct('/usr/bin/sms_tool', [ '-s' , storeL , '-d' , portR , '-f' , '%Y-%m-%d %H:%M' , '-j' , 'recv' , '2>/dev/null' ]))
|
||||
.then(function(res2) {
|
||||
if (res2) {
|
||||
|
||||
var table = document.getElementById('smsTable');
|
||||
while (table.rows.length > 1) { table.deleteRow(1); }
|
||||
|
||||
var start = res2.substring(7);
|
||||
var end = start.substring(0,start.length-2);
|
||||
|
||||
var json = JSON.parse(end);
|
||||
|
||||
var aidx = [];
|
||||
|
||||
/* Merging messages */
|
||||
if (smsM == "1") {
|
||||
|
||||
var result = [];
|
||||
|
||||
if (algo == "Advanced")
|
||||
{
|
||||
switch (direct) {
|
||||
case 'Start':
|
||||
var Data = json.sort((a, b) => {
|
||||
if (a.timestamp === b.timestamp && a.sender === b.sender) {
|
||||
return a.part - b.part;
|
||||
} else if (a.timestamp === b.timestamp) {
|
||||
return a.sender - b.sender;
|
||||
} else {
|
||||
return a.timestamp.localeCompare(b.timestamp);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'End':
|
||||
var Data = json.sort((a, b) => {
|
||||
if (a.timestamp === b.timestamp && a.sender === b.sender) {
|
||||
return b.part - a.part;
|
||||
} else if (a.timestamp === b.timestamp) {
|
||||
return a.sender - b.sender;
|
||||
} else {
|
||||
return a.timestamp.localeCompare(b.timestamp);
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
var SortedSMS = Data.sort((function (a, b) { return new Date(b.timestamp) - new Date(a.timestamp) }));
|
||||
var combinedjson = {};
|
||||
|
||||
for (const parts of SortedSMS) {
|
||||
const { sender, timestamp, total, content, index } = parts;
|
||||
|
||||
if (total) {
|
||||
const key = `${sender}-${timestamp}-${total}`;
|
||||
if (combinedjson[key]) {
|
||||
combinedjson[key].content += content;
|
||||
combinedjson[key].index += '-' + index;
|
||||
} else {
|
||||
combinedjson[key] = { sender, timestamp, total, content, index };
|
||||
}
|
||||
} else {
|
||||
const newkey = `${sender}-${timestamp}-${index}`;
|
||||
combinedjson[newkey] = { sender, timestamp, total, content, index };
|
||||
}
|
||||
}
|
||||
var result = Object.values(combinedjson); }
|
||||
|
||||
if (algo == "Simple")
|
||||
{
|
||||
var SortedSMS = json.sort((function (a, b) { return new Date(b.timestamp) - new Date(a.timestamp) }));
|
||||
|
||||
SortedSMS.forEach(function (o) {
|
||||
if (!this[o.sender]) {
|
||||
this[o.sender] = { index: o.index, sender: o.sender, timestamp: o.timestamp, part: o.part, total: o.total, content: o.content };
|
||||
result.push(this[o.sender]);
|
||||
return;
|
||||
}
|
||||
if (this[o.sender].total == o.total && this[o.sender].timestamp == o.timestamp && this[o.sender].sender == o.sender && this[o.sender].part > 0) {
|
||||
this[o.sender].index += '-' + o.index;
|
||||
this[o.sender].content += o.content;}
|
||||
else {
|
||||
this[o.sender] = { index: o.index, sender: o.sender, timestamp: o.timestamp, part: o.part, total: o.total, content: o.content };
|
||||
result.push(this[o.sender]);
|
||||
return;
|
||||
}
|
||||
}, Object.create(null));
|
||||
}
|
||||
if (u){
|
||||
var Lres = L.resource('icons/newdelsms.png');
|
||||
var iconz = String.format('<img style="width: 24px; height: 24px; "src="%s"/>', Lres);
|
||||
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var row = table.insertRow(-1);
|
||||
var cell1 = row.insertCell(0);
|
||||
var cell2 = row.insertCell(0);
|
||||
var cell3 = row.insertCell(0);
|
||||
var cell4 = row.insertCell(0);
|
||||
cell4.innerHTML = "<input type='checkbox' name='smsn' id="+result[i].index+","+" />"+iconz;
|
||||
if (result[i].sender.includes(hide)) {
|
||||
var removeLast5 = result[i].sender.slice(0, -5);
|
||||
cell3.innerHTML = removeLast5 + '#####';
|
||||
} else {
|
||||
cell3.innerHTML = result[i].sender;
|
||||
}
|
||||
|
||||
cell2.innerHTML = result[i].timestamp;
|
||||
cell1.innerHTML = result[i].content.replace(/\s+/g, ' ').trim();
|
||||
aidx.push(result[i].index+'-');
|
||||
}
|
||||
|
||||
var axx = aidx.toString();
|
||||
axx = axx.replace(/,/g, ' ');
|
||||
axx = axx.replace(/-/g, ' ');
|
||||
|
||||
uci.set('sms_tool_js', '@sms_tool_js[0]', 'sms_count_index', L.toArray(axx).join(' '));
|
||||
uci.set('sms_tool_js', '@sms_tool_js[0]', 'sms_count', L.toArray(u).join(' '));
|
||||
uci.save();
|
||||
uci.apply();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* No merging messages */
|
||||
if (smsM == "0") {
|
||||
|
||||
/* Sorting messages by delivery time */
|
||||
var sortbyTime = json.sort((function (a, b) { return new Date(b.timestamp) - new Date(a.timestamp) }));
|
||||
|
||||
/* Sorting messages by parts */
|
||||
var sortedData = sortbyTime.sort((a, b) => {
|
||||
if (a.timestamp === b.timestamp && a.sender === b.sender && a.total === b.total) {
|
||||
return a.part - b.part;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
if (u){
|
||||
|
||||
var Lres = L.resource('icons/newdelsms.png');
|
||||
var iconz = String.format('<img style="width: 24px; height: 24px; "src="%s"/>', Lres);
|
||||
|
||||
for (var i = 0; i < sortedData.length; i++) {
|
||||
var row = table.insertRow(-1);
|
||||
var cell1 = row.insertCell(0);
|
||||
var cell2 = row.insertCell(0);
|
||||
var cell3 = row.insertCell(0);
|
||||
var cell4 = row.insertCell(0);
|
||||
cell4.innerHTML = "<input type='checkbox' name='smsn' id="+sortedData[i].index+","+" />"+iconz;
|
||||
if (sortedData[i].sender.includes(hide)) {
|
||||
var removeLast5 = sortedData[i].sender.slice(0, -5);
|
||||
cell3.innerHTML = removeLast5 + '#####';
|
||||
} else {
|
||||
cell3.innerHTML = sortedData[i].sender;
|
||||
}
|
||||
cell2.innerHTML = sortedData[i].timestamp;
|
||||
cell1.innerHTML = sortedData[i].content.replace(/\s+/g, ' ').trim();
|
||||
aidx.push(sortedData[i].index+'-');
|
||||
|
||||
}
|
||||
|
||||
var axx = aidx.toString();
|
||||
axx = axx.replace(/,/g, ' ');
|
||||
axx = axx.replace(/-/g, ' ');
|
||||
|
||||
uci.set('sms_tool_js', '@sms_tool_js[0]', 'sms_count_index', L.toArray(axx).join(' '));
|
||||
uci.set('sms_tool_js', '@sms_tool_js[0]', 'sms_count', L.toArray(u).join(' '));
|
||||
uci.save();
|
||||
uci.apply();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
if ( t.lenght < 1 )
|
||||
{
|
||||
msg_bar(Math.floor(u), t);
|
||||
}
|
||||
ui.addNotification(null, E('p', _('Please set the port for communication with the modem')), 'info');
|
||||
}
|
||||
|
||||
if (document.getElementById('msg')) {
|
||||
msg_bar(Math.floor(u), t);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var v = E([], [
|
||||
E('h2', _('SMS Messages')),
|
||||
E('div', { 'class': 'cbi-map-descr' }, _('User interface for reading messages using sms-tool. More information about the sms-tool on the %seko.one.pl forum%s.').format('<a href="https://eko.one.pl/?p=openwrt-sms_tool" target="_blank">', '</a>')),
|
||||
|
||||
E('h3', _('Received Messages')),
|
||||
E('table', { 'class': 'table' }, [
|
||||
E('tr', { 'class': 'tr' }, [
|
||||
E('td', { 'class': 'td left', 'width': '33%' }, [ _('Message storage area') ]),
|
||||
E('td', { 'class': 'td' }, [
|
||||
E('div', [
|
||||
E('label', {
|
||||
'data-tooltip': _('Any change in the area from which SMS messages will be read requires refreshing the messages')
|
||||
}, [
|
||||
E('input', {
|
||||
'type': 'radio',
|
||||
'name': 'filter_area',
|
||||
'value': 'sim',
|
||||
'change': ui.createHandlerFn(this, 'handleSWarea'),
|
||||
'checked': true
|
||||
}),
|
||||
' ',
|
||||
_('SIM card')
|
||||
]),
|
||||
' \u00a0 ',
|
||||
E('label', {
|
||||
'data-tooltip': _('Any change in the area from which SMS messages will be read requires refreshing the messages')
|
||||
}, [
|
||||
E('input', {
|
||||
'type': 'radio',
|
||||
'name': 'filter_area',
|
||||
'value': 'memory',
|
||||
'change': ui.createHandlerFn(this, 'handleSWarea')
|
||||
}),
|
||||
' ',
|
||||
_('Modem memory')
|
||||
])
|
||||
])
|
||||
])
|
||||
]),
|
||||
E('tr', { 'class': 'tr' }, [
|
||||
E('td', { 'class': 'td left', 'width': '33%' }, [ _('Storage used / Total capacity') ]),
|
||||
E('td', { 'class': 'td' }, [
|
||||
E('div', { 'class': 'right' }, [
|
||||
E('div', {
|
||||
'id': 'msg',
|
||||
'class': 'cbi-progressbar',
|
||||
'title': '-'
|
||||
}, E('div')),
|
||||
E('div', { 'class': 'right' }, [
|
||||
E('div', {
|
||||
'style': 'text-align:center;font-size:90%',
|
||||
'id': 'deleteinfo'
|
||||
}, [ '' ]),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
|
||||
E('div', { 'class': 'right' }, [
|
||||
E('button', {
|
||||
//'class': 'cbi-button cbi-button-negative important',
|
||||
'class': 'cbi-button cbi-button-remove',
|
||||
'id': 'execute',
|
||||
'click': ui.createHandlerFn(this, 'handleDelete')
|
||||
}, [ _('Delete message(s)') ]),
|
||||
'\xa0\xa0\xa0',
|
||||
E('button', {
|
||||
'class': 'cbi-button cbi-button-add',
|
||||
'id': 'clr',
|
||||
'click': ui.createHandlerFn(this, 'handleRefresh')
|
||||
}, [ _('Refresh messages') ]),
|
||||
|
||||
]),
|
||||
|
||||
E('p'),
|
||||
|
||||
E('table', { 'class': 'table' , 'id' : 'smsTable' }, [
|
||||
E('tr', { 'class': 'tr table-titles' }, [
|
||||
E('th', { 'class': 'th checker' },
|
||||
E('input', {
|
||||
'id': 'ch-all',
|
||||
'type': 'checkbox',
|
||||
'name': 'checkall',
|
||||
'disabled': null,
|
||||
'checked': null,
|
||||
'click': ui.createHandlerFn(this, 'handleSelect')
|
||||
}), '',
|
||||
),
|
||||
E('th', { 'class': 'th from' }, _('From')),
|
||||
E('th', { 'class': 'th received' }, _('Received')),
|
||||
E('th', { 'class': 'th center message' }, _('Message'))
|
||||
])
|
||||
]),
|
||||
]);
|
||||
return v;
|
||||
},
|
||||
|
||||
handleSaveApply: null,
|
||||
handleSave: null,
|
||||
handleReset: null
|
||||
});
|
||||
@@ -0,0 +1,187 @@
|
||||
'use strict';
|
||||
'require dom';
|
||||
'require form';
|
||||
'require fs';
|
||||
'require ui';
|
||||
'require uci';
|
||||
'require view';
|
||||
|
||||
/*
|
||||
Copyright 2022-2025 Rafał Wabik - IceG - From eko.one.pl forum
|
||||
|
||||
Licensed to the GNU General Public License v3.0.
|
||||
*/
|
||||
|
||||
return view.extend({
|
||||
handleCommand: function(exec, args) {
|
||||
let buttons = document.querySelectorAll('.cbi-button');
|
||||
|
||||
for (let i = 0; i < buttons.length; i++)
|
||||
buttons[i].setAttribute('disabled', 'true');
|
||||
|
||||
return fs.exec(exec, args).then(function(res) {
|
||||
let out = document.querySelector('.atcommand-output');
|
||||
out.style.display = '';
|
||||
|
||||
res.stdout = res.stdout?.replace(/^(?=\n)$|^\s*|\s*$|\n\n+/gm, "") || '';
|
||||
res.stderr = res.stderr?.replace(/^(?=\n)$|^\s*|\s*$|\n\n+/gm, "") || '';
|
||||
|
||||
if (res.stdout === undefined || res.stderr === undefined || res.stderr.includes('undefined') || res.stdout.includes('undefined')) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
dom.content(out, [ res.stdout || '', res.stderr || '' ]);
|
||||
}
|
||||
|
||||
}).catch(function(err) {
|
||||
if (res.stdout === undefined || res.stderr === undefined || res.stderr.includes('undefined') || res.stdout.includes('undefined')) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
ui.addNotification(null, E('p', [ err ]));
|
||||
}
|
||||
}).finally(function() {
|
||||
for (let i = 0; i < buttons.length; i++)
|
||||
buttons[i].removeAttribute('disabled');
|
||||
|
||||
});
|
||||
},
|
||||
|
||||
handleGo: function(ev) {
|
||||
let atcmd = document.getElementById('cmdvalue').value;
|
||||
let sections = uci.sections('sms_tool_js');
|
||||
let port = sections[0].atport;
|
||||
|
||||
if ( atcmd.length < 2 )
|
||||
{
|
||||
ui.addNotification(null, E('p', _('Please specify the command to send')), 'info');
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if ( !port )
|
||||
{
|
||||
ui.addNotification(null, E('p', _('Please set the port for communication with the modem')), 'info');
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
//sms_tool -d /dev/ttyUSB1 at "ati"
|
||||
return this.handleCommand('sms_tool', [ '-d' , port , 'at' , atcmd ]);
|
||||
}
|
||||
}
|
||||
if ( !port )
|
||||
{
|
||||
ui.addNotification(null, E('p', _('Please set the port for communication with the modem')), 'info');
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
handleClear: function(ev) {
|
||||
let out = document.querySelector('.atcommand-output');
|
||||
out.style.display = 'none';
|
||||
|
||||
let ov = document.getElementById('cmdvalue');
|
||||
ov.value = '';
|
||||
|
||||
document.getElementById('cmdvalue').focus();
|
||||
},
|
||||
|
||||
handleCopy: function(ev) {
|
||||
let out = document.querySelector('.atcommand-output');
|
||||
out.style.display = 'none';
|
||||
|
||||
let ov = document.getElementById('cmdvalue');
|
||||
ov.value = '';
|
||||
let x = document.getElementById('tk').value;
|
||||
ov.value = x;
|
||||
},
|
||||
|
||||
load: function() {
|
||||
return Promise.all([
|
||||
L.resolveDefault(fs.read_direct('/etc/modem/atcmmds.user'), null),
|
||||
uci.load('sms_tool_js')
|
||||
]);
|
||||
},
|
||||
|
||||
render: function (loadResults) {
|
||||
|
||||
let info = _('User interface for sending AT commands using sms-tool. More information about the sms-tool on the %seko.one.pl forum%s.').format('<a href="https://eko.one.pl/?p=openwrt-sms_tool" target="_blank">', '</a>');
|
||||
|
||||
return E('div', { 'class': 'cbi-map', 'id': 'map' }, [
|
||||
E('h2', {}, [ _('AT Commands') ]),
|
||||
E('div', { 'class': 'cbi-map-descr'}, info),
|
||||
E('hr'),
|
||||
E('div', { 'class': 'cbi-section' }, [
|
||||
E('div', { 'class': 'cbi-section-node' }, [
|
||||
E('div', { 'class': 'cbi-value' }, [
|
||||
E('label', { 'class': 'cbi-value-title' }, [ _('User AT commands') ]),
|
||||
E('div', { 'class': 'cbi-value-field' }, [
|
||||
E('select', { 'class': 'cbi-input-select',
|
||||
'id': 'tk',
|
||||
'style': 'margin:5px 0; width:100%;',
|
||||
'change': ui.createHandlerFn(this, 'handleCopy'),
|
||||
'mousedown': ui.createHandlerFn(this, 'handleCopy')
|
||||
},
|
||||
(loadResults[0] || "").trim().split("\n").map(function(cmd) {
|
||||
let fields = cmd.split(/;/);
|
||||
let name = fields[0];
|
||||
let code = fields[1] || fields[0];
|
||||
return E('option', { 'value': code }, name );
|
||||
})
|
||||
)
|
||||
])
|
||||
]),
|
||||
E('div', { 'class': 'cbi-value' }, [
|
||||
E('label', { 'class': 'cbi-value-title' }, [ _('Command to send') ]),
|
||||
E('div', { 'class': 'cbi-value-field' }, [
|
||||
E('input', {
|
||||
'style': 'margin:5px 0; width:100%;',
|
||||
'type': 'text',
|
||||
'id': 'cmdvalue',
|
||||
'data-tooltip': _('Press [Enter] to send the command, press [Delete] to delete the command'),
|
||||
'keydown': function(ev) {
|
||||
if (ev.keyCode === 13)
|
||||
{
|
||||
let execBtn = document.getElementById('execute');
|
||||
if (execBtn) {
|
||||
execBtn.click();
|
||||
}
|
||||
}
|
||||
if (ev.keyCode === 46)
|
||||
{
|
||||
let del = document.getElementById('cmdvalue');
|
||||
if (del) {
|
||||
let ov = document.getElementById('cmdvalue');
|
||||
ov.value = '';
|
||||
document.getElementById('cmdvalue').focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
])
|
||||
]),
|
||||
])
|
||||
]),
|
||||
E('hr'),
|
||||
E('div', { 'class': 'right' }, [
|
||||
E('button', {
|
||||
'class': 'cbi-button cbi-button-remove',
|
||||
'id': 'clr',
|
||||
'click': ui.createHandlerFn(this, 'handleClear')
|
||||
}, [ _('Clear form') ]),
|
||||
'\xa0\xa0\xa0',
|
||||
E('button', {
|
||||
'class': 'cbi-button cbi-button-action important',
|
||||
'id': 'execute',
|
||||
'click': ui.createHandlerFn(this, 'handleGo')
|
||||
}, [ _('Send command') ]),
|
||||
]),
|
||||
E('p', _('Reply')),
|
||||
E('pre', { 'class': 'atcommand-output', 'style': 'display:none; border: 1px solid var(--border-color-medium); border-radius: 5px; font-family: monospace' }),
|
||||
|
||||
]);
|
||||
},
|
||||
|
||||
handleSaveApply: null,
|
||||
handleSave: null,
|
||||
handleReset: null
|
||||
})
|
||||
@@ -0,0 +1,329 @@
|
||||
'use strict';
|
||||
'require dom';
|
||||
'require form';
|
||||
'require fs';
|
||||
'require ui';
|
||||
'require uci';
|
||||
'require view';
|
||||
|
||||
/*
|
||||
Copyright 2022-2025 Rafał Wabik - IceG - From eko.one.pl forum
|
||||
|
||||
Licensed to the GNU General Public License v3.0.
|
||||
*/
|
||||
|
||||
return view.extend({
|
||||
handleCommand: function(exec, args) {
|
||||
let buttons = document.querySelectorAll('.cbi-button');
|
||||
|
||||
for (let i = 0; i < buttons.length; i++)
|
||||
buttons[i].setAttribute('disabled', 'true');
|
||||
|
||||
return fs.exec(exec, args).then(function(res) {
|
||||
let out = document.querySelector('.smscommand-output');
|
||||
out.style.display = '';
|
||||
|
||||
res.stdout = res.stdout?.replace(/^(?=\n)$|^\s*|\s*$|\n\n+/gm, "") || '';
|
||||
res.stderr = res.stderr?.replace(/^(?=\n)$|^\s*|\s*$|\n\n+/gm, "") || '';
|
||||
|
||||
let cut = res.stdout;
|
||||
cut = cut.substr(0, 20);
|
||||
if ( cut == "sms sent sucessfully" ) {
|
||||
res.stdout = _('SMS sent sucessfully');
|
||||
}
|
||||
|
||||
dom.content(out, [ res.stdout || '', res.stderr || '' ]);
|
||||
|
||||
}).catch(function(err) {
|
||||
ui.addNotification(null, E('p', [ err ]))
|
||||
}).finally(function() {
|
||||
for (let i = 0; i < buttons.length; i++)
|
||||
buttons[i].removeAttribute('disabled');
|
||||
});
|
||||
},
|
||||
|
||||
handleGo: function(ev) {
|
||||
let phn = document.getElementById('phonenumber').value;
|
||||
let sections = uci.sections('sms_tool_js');
|
||||
let port = sections[0].sendport;
|
||||
let dx = sections[0].delay * 1000;
|
||||
let get_smstxt = document.getElementById('smstext').value;
|
||||
|
||||
let elem = document.getElementById('execute');
|
||||
let vN = elem.innerText;
|
||||
|
||||
if (vN.includes(_('Send to number')) == true)
|
||||
{
|
||||
if ( phn.length < 3 )
|
||||
{
|
||||
ui.addNotification(null, E('p', _('Please enter phone number')), 'info');
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if ( !port )
|
||||
{
|
||||
ui.addNotification(null, E('p', _('Please set the port for communication with the modem')), 'info');
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if ( get_smstxt.length < 1 )
|
||||
{
|
||||
ui.addNotification(null, E('p', _('Please enter a message text')), 'info');
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// sms_tool -d /dev/ttyUSB1 send 48500500500 "MSG"
|
||||
return this.handleCommand('sms_tool', [ '-d' , port , 'send' , phn , get_smstxt ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !port )
|
||||
{
|
||||
ui.addNotification(null, E('p', _('Please set the port for communication with the modem')), 'info');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if ( !port )
|
||||
{
|
||||
ui.addNotification(null, E('p', _('Please set the port for communication with the modem')), 'info');
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if ( get_smstxt.length < 1 )
|
||||
{
|
||||
ui.addNotification(null, E('p', _('Please enter a message text')), 'info');
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// sms_tool -d /dev/ttyUSB1 send 48500500500 "MSG"
|
||||
let xs = document.getElementById('pb');
|
||||
|
||||
let phone, i;
|
||||
res.stdout = '';
|
||||
|
||||
for (let i = 0; i < xs.length; i++) {
|
||||
(function(i) {
|
||||
setTimeout(function() {
|
||||
phone = xs.options[i].value;
|
||||
|
||||
let out = document.querySelector('.smscommand-output');
|
||||
out.style.display = '';
|
||||
|
||||
fs.exec_direct('/usr/bin/sms_tool', [ '-d' , port , 'send' , phone , get_smstxt ]);
|
||||
|
||||
res.stdout += (i+1)+_('/')+xs.length+' * '+_('[Bot] Message sent to number:') + ' ' + phone +'\n';
|
||||
res.stdout = res.stdout.replace(/undefined/g, "");
|
||||
|
||||
dom.content(out, [ res.stdout || '' ]);
|
||||
|
||||
}, dx * i);
|
||||
})(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handleClear: function(ev) {
|
||||
let out = document.querySelector('.smscommand-output');
|
||||
out.style.display = '';
|
||||
out.style.display = 'none';
|
||||
|
||||
let ovc = document.getElementById('phonenumber');
|
||||
let ov2 = document.getElementById('smstext');
|
||||
ov2.value = '';
|
||||
|
||||
document.getElementById('counter').innerHTML = '160';
|
||||
|
||||
let prefixnum, sections = uci.sections('sms_tool_js');
|
||||
let addprefix = sections[0].prefix;
|
||||
if ( addprefix == '1' )
|
||||
{
|
||||
prefixnum = sections[0].pnumber;
|
||||
ovc.value = prefixnum;
|
||||
}
|
||||
else {
|
||||
ovc.value = '';
|
||||
}
|
||||
|
||||
document.getElementById('phonenumber').focus();
|
||||
},
|
||||
|
||||
handleCopy: function(ev) {
|
||||
let out = document.querySelector('.smscommand-output');
|
||||
out.style.display = 'none';
|
||||
|
||||
let ov = document.getElementById('phonenumber');
|
||||
ov.value = '';
|
||||
let x = document.getElementById('pb').value;
|
||||
ov.value = x;
|
||||
},
|
||||
|
||||
load: function() {
|
||||
return Promise.all([
|
||||
L.resolveDefault(fs.read_direct('/etc/modem/phonebook.user'), null),
|
||||
uci.load('sms_tool_js')
|
||||
]);
|
||||
},
|
||||
|
||||
render: function (loadResults) {
|
||||
|
||||
let group, prefixnum, sections = uci.sections('sms_tool_js');
|
||||
|
||||
if ( sections[0].sendingroup == '1' )
|
||||
{
|
||||
group = 1;
|
||||
}
|
||||
else {
|
||||
group = '';
|
||||
}
|
||||
|
||||
if ( sections[0].prefix == '1' ) {
|
||||
prefixnum = sections[0].pnumber;
|
||||
}
|
||||
if ( sections[0].information == '1' ) {
|
||||
ui.addNotification(null, E('p', _('The phone number should be preceded by the country prefix (for Poland it is 48, without +). If the number is 5, 4 or 3 characters, it is treated as.. short and should not be preceded by a country prefix.') ), 'info');
|
||||
}
|
||||
|
||||
let info = _('User interface for sending messages using sms-tool. More information about the sms-tool on the %seko.one.pl forum%s.').format('<a href="https://eko.one.pl/?p=openwrt-sms_tool" target="_blank">', '</a>');
|
||||
|
||||
return E('div', { 'class': 'cbi-map', 'id': 'map' }, [
|
||||
E('h2', {}, [ _('SMS Messages') ]),
|
||||
E('div', { 'class': 'cbi-map-descr'}, info),
|
||||
E('hr'),
|
||||
E('div', { 'class': 'cbi-section' }, [
|
||||
E('div', { 'class': 'cbi-section-node' }, [
|
||||
E('div', { 'class': 'cbi-value' }, [
|
||||
E('label', { 'class': 'cbi-value-title' }, [ _('User contacts') ]),
|
||||
E('div', { 'class': 'cbi-value-field' }, [
|
||||
E('select', { 'class': 'cbi-input-select',
|
||||
'id': 'pb',
|
||||
'style': 'margin:5px 0; width:100%;',
|
||||
'change': ui.createHandlerFn(this, 'handleCopy'),
|
||||
'mousedown': ui.createHandlerFn(this, 'handleCopy')
|
||||
},
|
||||
(loadResults[0] || "").trim().split("\n").map(function(cmd) {
|
||||
let fields = cmd.split(/;/);
|
||||
let name = fields[0];
|
||||
let code = fields[1] || fields[0];
|
||||
return E('option', { 'value': code }, name );
|
||||
})
|
||||
)
|
||||
])
|
||||
]),
|
||||
E('div', { 'class': 'cbi-value' }, [
|
||||
E('label', { 'class': 'cbi-value-title' }, [ _('Send to') ]),
|
||||
E('div', { 'class': 'cbi-value-field' }, [
|
||||
E('input', {
|
||||
'style': 'margin:5px 0; width:100%;',
|
||||
'type': 'text',
|
||||
'id': 'phonenumber',
|
||||
'value': prefixnum,
|
||||
'oninput': "this.value = this.value.replace(/[^0-9.]/g, '');",
|
||||
'data-tooltip': _('Press [Delete] to delete the phone number'),
|
||||
'keydown': function(ev) {
|
||||
if (ev.keyCode === 46)
|
||||
{
|
||||
let del = document.getElementById('phonenumber');
|
||||
if (del) {
|
||||
let ovc = document.getElementById('phonenumber');
|
||||
let prefixnum, sections = uci.sections('sms_tool_js');
|
||||
let addprefix = sections[0].prefix;
|
||||
if ( addprefix == '1' )
|
||||
{
|
||||
prefixnum = sections[0].pnumber;
|
||||
ovc.value = prefixnum;
|
||||
}
|
||||
else {
|
||||
ovc.value = '';
|
||||
}
|
||||
document.getElementById('phonenumber').focus();
|
||||
}
|
||||
}
|
||||
},
|
||||
}),
|
||||
])
|
||||
]),
|
||||
E('div', { 'class': 'cbi-value' }, [
|
||||
E('label', { 'class': 'cbi-value-title' }, [ _('Message text') ]),
|
||||
E('div', { 'class': 'cbi-value-field' }, [
|
||||
E('textarea', {
|
||||
'id': 'smstext',
|
||||
'style': 'width: 100%; resize: vertical; height:80px; max-height:80px; min-height:80px; min-width:100%;',
|
||||
'wrap': 'on',
|
||||
'rows': '3',
|
||||
'placeholder': _(''),
|
||||
'maxlength': '160',
|
||||
'data-tooltip': _('Press [Delete] to delete the content of the message'),
|
||||
'keydown': function(ev) {
|
||||
if (ev.keyCode === 46)
|
||||
{
|
||||
let del = document.getElementById('smstext');
|
||||
if (del) {
|
||||
let ovtxt = document.getElementById('smstext');
|
||||
ovtxt.value = '';
|
||||
document.getElementById('smstext').focus();
|
||||
}
|
||||
}
|
||||
},
|
||||
'keyup': function(ev) {
|
||||
document.getElementById('counter').innerHTML = (160 - document.getElementById('smstext').value.length);
|
||||
|
||||
this.value = this.value.replace(/ą/g, 'a').replace(/Ą/g, 'A');
|
||||
this.value = this.value.replace(/ć/g, 'c').replace(/Ć/g, 'C');
|
||||
this.value = this.value.replace(/ę/g, 'e').replace(/Ę/g, 'E');
|
||||
this.value = this.value.replace(/ł/g, 'l').replace(/Ł/g, 'L');
|
||||
this.value = this.value.replace(/ń/g, 'n').replace(/Ń/g, 'N');
|
||||
this.value = this.value.replace(/ó/g, 'o').replace(/Ó/g, 'O');
|
||||
this.value = this.value.replace(/ś/g, 's').replace(/Ś/g, 'S');
|
||||
this.value = this.value.replace(/ż/g, 'z').replace(/Ż/g, 'Z');
|
||||
this.value = this.value.replace(/ź/g, 'z').replace(/Ź/g, 'Z');
|
||||
}
|
||||
}),
|
||||
E('div', { 'class': 'left' }, [
|
||||
E('br'),
|
||||
E('label', { 'id': 'counter' }, [ _('160') ])
|
||||
])
|
||||
]),
|
||||
]),
|
||||
|
||||
])
|
||||
]),
|
||||
E('hr'),
|
||||
E('div', { 'class': 'right' }, [
|
||||
E('button', {
|
||||
'class': 'cbi-button cbi-button-remove',
|
||||
'id': 'clr',
|
||||
'click': ui.createHandlerFn(this, 'handleClear')
|
||||
}, [ _('Clear form') ]),
|
||||
'\xa0\xa0\xa0',
|
||||
E('span', { 'class': 'diag-action' }, [
|
||||
group ? new ui.ComboButton('send', {
|
||||
'send': '%s %s'.format(_('Send'), _('to number')),
|
||||
'sendg': '%s %s'.format(_('Send'), _('to group')),
|
||||
}, {
|
||||
'click': ui.createHandlerFn(this, 'handleGo'),
|
||||
'id': 'execute',
|
||||
'classes': {
|
||||
'send': 'cbi-button cbi-button-action important',
|
||||
'sendg': 'cbi-button cbi-button-action important',
|
||||
},
|
||||
'id': 'execute',
|
||||
}).render() : E('button', {
|
||||
'class': 'cbi-button cbi-button-action important',
|
||||
'id': 'execute',
|
||||
'click': ui.createHandlerFn(this, 'handleGo')
|
||||
}, [ _('Send to number') ]),
|
||||
]),
|
||||
]),
|
||||
E('p', _('Status')),
|
||||
E('pre', { 'class': 'smscommand-output', 'id': 'ans', 'style': 'display:none; border: 1px solid var(--border-color-medium); border-radius: 5px; font-family: monospace' }),
|
||||
]);
|
||||
},
|
||||
|
||||
handleSaveApply: null,
|
||||
handleSave: null,
|
||||
handleReset: null
|
||||
})
|
||||
@@ -0,0 +1,385 @@
|
||||
'use strict';
|
||||
'require dom';
|
||||
'require form';
|
||||
'require fs';
|
||||
'require ui';
|
||||
'require uci';
|
||||
'require view';
|
||||
|
||||
/*
|
||||
Copyright 2022-2025 Rafał Wabik - IceG - From eko.one.pl forum
|
||||
|
||||
Licensed to the GNU General Public License v3.0.
|
||||
*/
|
||||
|
||||
return view.extend({
|
||||
handleCommand: function(exec, args) {
|
||||
let buttons = document.querySelectorAll('.cbi-button');
|
||||
|
||||
for (let i = 0; i < buttons.length; i++)
|
||||
buttons[i].setAttribute('disabled', 'true');
|
||||
|
||||
return fs.exec(exec, args).then(function(res) {
|
||||
let out = document.querySelector('.ussdcommand-output');
|
||||
let fullhistory = document.getElementById('history-full')?.checked;
|
||||
let reversereplies = document.getElementById('reverse-replies')?.checked;
|
||||
out.style.display = '';
|
||||
|
||||
res.stdout = res.stdout?.replace(/^(?=\n)$|^\s*|\s*$|\n\n+/gm, "") || '';
|
||||
res.stderr = res.stderr?.replace(/^(?=\n)$|^\s*|\s*$|\n\n+/gm, "") || '';
|
||||
|
||||
if (res.stdout === undefined || res.stderr === undefined || res.stderr.includes('undefined') || res.stdout.includes('undefined')) {
|
||||
return;
|
||||
} else {
|
||||
let cut = res.stderr;
|
||||
if ( cut.length > 2 ) {
|
||||
if (cut.includes('error: 0'))
|
||||
res.stdout = _('Phone/Modem failure.');
|
||||
if (cut.includes('error: 1'))
|
||||
res.stdout = _('No connection to phone.');
|
||||
if (cut.includes('error: 2'))
|
||||
res.stdout = _('Phone/Modem adapter link reserved.');
|
||||
if (cut.includes('error: 3'))
|
||||
res.stdout = _('Operation not allowed.');
|
||||
if (cut.includes('error: 4'))
|
||||
res.stdout = _('Operation not supported.');
|
||||
if (cut.includes('error: 5'))
|
||||
res.stdout = _('PH_SIM PIN required.');
|
||||
if (cut.includes('error: 6'))
|
||||
res.stdout = _('PH_FSIM PIN required.');
|
||||
if (cut.includes('error: 7'))
|
||||
res.stdout = _('PH_FSIM PUK required.');
|
||||
if (cut.includes('error: 10'))
|
||||
res.stdout = _('SIM not inserted.');
|
||||
if (cut.includes('error: 11'))
|
||||
res.stdout = _('SIM PIN required.');
|
||||
if (cut.includes('error: 12'))
|
||||
res.stdout = _('SIM PUK required.');
|
||||
if (cut.includes('error: 13'))
|
||||
res.stdout = _('SIM failure.');
|
||||
if (cut.includes('error: 14'))
|
||||
res.stdout = _('SIM busy.');
|
||||
if (cut.includes('error: 15'))
|
||||
res.stdout = _('SIM wrong.');
|
||||
if (cut.includes('error: 16'))
|
||||
res.stdout = _('Incorrect password.');
|
||||
if (cut.includes('error: 17'))
|
||||
res.stdout = _('SIM PIN2 required.');
|
||||
if (cut.includes('error: 18'))
|
||||
res.stdout = _('SIM PUK2 required.');
|
||||
if (cut.includes('error: 20'))
|
||||
res.stdout = _('Memory full.');
|
||||
if (cut.includes('error: 21'))
|
||||
res.stdout = _('Invalid index.');
|
||||
if (cut.includes('error: 22'))
|
||||
res.stdout = _('Not found.');
|
||||
if (cut.includes('error: 23'))
|
||||
res.stdout = _('Memory failure.');
|
||||
if (cut.includes('error: 24'))
|
||||
res.stdout = _('Text string too long.');
|
||||
if (cut.includes('error: 25'))
|
||||
res.stdout = _('Invalid characters in text string.');
|
||||
if (cut.includes('error: 26'))
|
||||
res.stdout = _('Dial string too long.');
|
||||
if (cut.includes('error: 27'))
|
||||
res.stdout = _('Invalid characters in dial string.');
|
||||
if (cut.includes('error: 30'))
|
||||
res.stdout = _('No network service.');
|
||||
if (cut.includes('error: 31'))
|
||||
res.stdout = _('Network timeout.');
|
||||
if (cut.includes('error: 32'))
|
||||
res.stdout = _('Network not allowed, emergency calls only.');
|
||||
if (cut.includes('error: 40'))
|
||||
res.stdout = _('Network personalization PIN required.');
|
||||
if (cut.includes('error: 41'))
|
||||
res.stdout = _('Network personalization PUK required.');
|
||||
if (cut.includes('error: 42'))
|
||||
res.stdout = _('Network subset personalization PIN required.');
|
||||
if (cut.includes('error: 43'))
|
||||
res.stdout = _('Network subset personalization PUK required.');
|
||||
if (cut.includes('error: 44'))
|
||||
res.stdout = _('Service provider personalization PIN required.');
|
||||
if (cut.includes('error: 45'))
|
||||
res.stdout = _('Service provider personalization PUK required.');
|
||||
if (cut.includes('error: 46'))
|
||||
res.stdout = _('Corporate personalization PIN required.');
|
||||
if (cut.includes('error: 47'))
|
||||
res.stdout = _('Corporate personalization PUK required.');
|
||||
if (cut.includes('error: 48'))
|
||||
res.stdout = _('PH-SIM PUK required.');
|
||||
if (cut.includes('error: 100'))
|
||||
res.stdout = _('Unknown error.');
|
||||
if (cut.includes('error: 103'))
|
||||
res.stdout = _('Illegal MS.');
|
||||
if (cut.includes('error: 106'))
|
||||
res.stdout = _('Illegal ME.');
|
||||
if (cut.includes('error: 107'))
|
||||
res.stdout = _('GPRS services not allowed.');
|
||||
if (cut.includes('error: 111'))
|
||||
res.stdout = _('PLMN not allowed.');
|
||||
if (cut.includes('error: 112'))
|
||||
res.stdout = _('Location area not allowed.');
|
||||
if (cut.includes('error: 113'))
|
||||
res.stdout = _('Roaming not allowed in this location area.');
|
||||
if (cut.includes('error: 126'))
|
||||
res.stdout = _('Operation temporary not allowed.');
|
||||
if (cut.includes('error: 132'))
|
||||
res.stdout = _('Service operation not supported.');
|
||||
if (cut.includes('error: 133'))
|
||||
res.stdout = _('Requested service option not subscribed.');
|
||||
if (cut.includes('error: 134'))
|
||||
res.stdout = _('Service option temporary out of order.');
|
||||
if (cut.includes('error: 148'))
|
||||
res.stdout = _('Unspecified GPRS error.');
|
||||
if (cut.includes('error: 149'))
|
||||
res.stdout = _('PDP authentication failure.');
|
||||
if (cut.includes('error: 150'))
|
||||
res.stdout = _('Invalid mobile class.');
|
||||
if (cut.includes('error: 256'))
|
||||
res.stdout = _('Operation temporarily not allowed.');
|
||||
if (cut.includes('error: 257'))
|
||||
res.stdout = _('Call barred.');
|
||||
if (cut.includes('error: 258'))
|
||||
res.stdout = _('Phone/Modem is busy.');
|
||||
if (cut.includes('error: 259'))
|
||||
res.stdout = _('User abort.');
|
||||
if (cut.includes('error: 260'))
|
||||
res.stdout = _('Invalid dial string.');
|
||||
if (cut.includes('error: 261'))
|
||||
res.stdout = _('SS not executed.');
|
||||
if (cut.includes('error: 262'))
|
||||
res.stdout = _('SIM Blocked.');
|
||||
if (cut.includes('error: 263'))
|
||||
res.stdout = _('Invalid block.');
|
||||
if (cut.includes('error: 527'))
|
||||
res.stdout = _('Please wait, and retry your selection later (Specific Modem Sierra).');
|
||||
if (cut.includes('error: 528'))
|
||||
res.stdout = _('Location update failure – emergency calls only (Specific Modem Sierra).');
|
||||
if (cut.includes('error: 529'))
|
||||
res.stdout = _('Selection failure – emergency calls only (Specific Modem Sierra).');
|
||||
if (cut.includes('error: 772'))
|
||||
res.stdout = _('SIM powered down.');
|
||||
dom.content(out, [ res.stderr || '', res.stdout ? ' > ' + res.stdout : '' ]);
|
||||
} else {
|
||||
if ( fullhistory ) {
|
||||
const ussdreply = (res.stdout + res.stderr).replace(/^\s*\n+/g, '');
|
||||
let ussdv = document.getElementById('cmdvalue');
|
||||
ussdv.value = '';
|
||||
document.getElementById('cmdvalue').focus();
|
||||
if (reversereplies) {
|
||||
out.innerText = ussdreply + (out.innerText.trim() ? '\n\n' + out.innerText : '');
|
||||
} else {
|
||||
out.innerText += '\n\n' + res.stdout + res.stderr;
|
||||
out.innerText = out.innerText.replace(/^\s*\n+/g, '');
|
||||
}
|
||||
} else {
|
||||
dom.content(out, [ res.stdout || '', res.stderr || '' ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).catch(function(err) {
|
||||
if (res.stdout === undefined || res.stderr === undefined || res.stderr.includes('undefined') || res.stdout.includes('undefined')) {
|
||||
return;
|
||||
} else {
|
||||
ui.addNotification(null, E('p', [ err ]));
|
||||
}
|
||||
}).finally(function() {
|
||||
for (let i = 0; i < buttons.length; i++)
|
||||
buttons[i].removeAttribute('disabled');
|
||||
});
|
||||
},
|
||||
|
||||
handleGo: function(ev) {
|
||||
let ussd = document.getElementById('cmdvalue').value;
|
||||
let sections = uci.sections('sms_tool_js');
|
||||
let port = sections[0].ussdport;
|
||||
let get_ussd = sections[0].ussd;
|
||||
let get_pdu = sections[0].pdu;
|
||||
let get_coding = sections[0].coding;
|
||||
let tool_args = [];
|
||||
|
||||
if ( ussd.length < 1 ) {
|
||||
ui.addNotification(null, E('p', _('Please specify the code to send')), 'info');
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !port ) {
|
||||
ui.addNotification(null, E('p', _('Please set the port for communication with the modem')), 'info');
|
||||
return false;
|
||||
}
|
||||
|
||||
tool_args.push('-d', port);
|
||||
if (get_ussd == '1')
|
||||
tool_args.push('-R');
|
||||
if (get_pdu == '1')
|
||||
tool_args.push('-r');
|
||||
if (get_coding && get_coding != 'auto')
|
||||
tool_args.push('-c', get_coding);
|
||||
tool_args.push('ussd', ussd);
|
||||
|
||||
return this.handleCommand('sms_tool', tool_args);
|
||||
},
|
||||
|
||||
handleClear: function(ev) {
|
||||
let out = document.querySelector('.ussdcommand-output');
|
||||
out.style.display = '';
|
||||
out.style.display = 'none';
|
||||
|
||||
let fullhistory = document.getElementById('history-full')?.checked;
|
||||
|
||||
if ( fullhistory ) {
|
||||
dom.content(out, [ '' ]);
|
||||
}
|
||||
|
||||
let ov = document.getElementById('cmdvalue');
|
||||
ov.value = '';
|
||||
|
||||
document.getElementById('cmdvalue').focus();
|
||||
},
|
||||
|
||||
handleClearOut: function(ev) {
|
||||
let out = document.querySelector('.ussdcommand-output');
|
||||
let fullhistory = document.getElementById('history-full')?.checked;
|
||||
|
||||
if ( fullhistory ) {
|
||||
out.style.display = '';
|
||||
out.style.display = 'none';
|
||||
dom.content(out, [ '' ]);
|
||||
document.getElementById("reverse-replies").disabled = false;
|
||||
document.getElementById("reverse-replies").checked = true;
|
||||
} else {
|
||||
document.getElementById("reverse-replies").disabled = true;
|
||||
document.getElementById("reverse-replies").checked = false;
|
||||
}
|
||||
},
|
||||
|
||||
handleCopy: function(ev) {
|
||||
let out = document.querySelector('.ussdcommand-output');
|
||||
let fullhistory = document.getElementById('history-full')?.checked;
|
||||
|
||||
if ( !fullhistory ) {
|
||||
out.style.display = 'none';
|
||||
}
|
||||
|
||||
let ov = document.getElementById('cmdvalue');
|
||||
ov.value = '';
|
||||
let x = document.getElementById('tk').value;
|
||||
ov.value = x;
|
||||
},
|
||||
|
||||
load: function() {
|
||||
|
||||
return Promise.all([
|
||||
L.resolveDefault(fs.read_direct('/etc/modem/ussdcodes.user'), null),
|
||||
uci.load('sms_tool_js')
|
||||
]);
|
||||
},
|
||||
|
||||
render: function (loadResults) {
|
||||
|
||||
let info = _('User interface for sending USSD codes using sms-tool. More information about the sms-tool on the %seko.one.pl forum%s.').format('<a href="https://eko.one.pl/?p=openwrt-sms_tool" target="_blank">', '</a>');
|
||||
|
||||
return E('div', { 'class': 'cbi-map', 'id': 'map' }, [
|
||||
E('h2', {}, [ _('USSD Codes') ]),
|
||||
E('div', { 'class': 'cbi-map-descr'}, info),
|
||||
E('hr'),
|
||||
E('div', { 'class': 'cbi-section' }, [
|
||||
E('div', { 'class': 'cbi-section-node' }, [
|
||||
E('div', { 'class': 'cbi-value' }, [
|
||||
E('label', { 'class': 'cbi-value-title' }, [ _('User USSD codes') ]),
|
||||
E('div', { 'class': 'cbi-value-field' }, [
|
||||
E('select', { 'class': 'cbi-input-select',
|
||||
'id': 'tk',
|
||||
'style': 'margin:5px 0; width:100%;',
|
||||
'change': ui.createHandlerFn(this, 'handleCopy'),
|
||||
'mousedown': ui.createHandlerFn(this, 'handleCopy')
|
||||
},
|
||||
(loadResults[0] || "").trim().split("\n").map(function(cmd) {
|
||||
let fields = cmd.split(/;/);
|
||||
let name = fields[0];
|
||||
let code = fields[1] || fields[0];
|
||||
return E('option', { 'value': code }, name );
|
||||
})
|
||||
)
|
||||
])
|
||||
]),
|
||||
E('div', { 'class': 'cbi-value' }, [
|
||||
E('label', { 'class': 'cbi-value-title' }, [ _('Code to send') ]),
|
||||
E('div', { 'class': 'cbi-value-field' }, [
|
||||
E('input', {
|
||||
'style': 'margin:5px 0; width:100%;',
|
||||
'type': 'text',
|
||||
'id': 'cmdvalue',
|
||||
'data-tooltip': _('Press [Enter] to send the code, press [Delete] to delete the code'),
|
||||
'keydown': function(ev) {
|
||||
if (ev.keyCode === 13) {
|
||||
let execBtn = document.getElementById('execute');
|
||||
if (execBtn) {
|
||||
execBtn.click();
|
||||
}
|
||||
}
|
||||
if (ev.keyCode === 46) {
|
||||
let del = document.getElementById('cmdvalue');
|
||||
if (del) {
|
||||
let ov = document.getElementById('cmdvalue');
|
||||
ov.value = '';
|
||||
document.getElementById('cmdvalue').focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
])
|
||||
]),
|
||||
|
||||
])
|
||||
]),
|
||||
E('div', { 'class': 'right' }, [
|
||||
E('label', { 'class': 'cbi-checkbox' }, [
|
||||
E('input', {
|
||||
'id': 'history-full',
|
||||
'click': ui.createHandlerFn(this, 'handleClearOut'),
|
||||
'data-tooltip': _('Check this option if you need to use the menu built on USSD codes'),
|
||||
'type': 'checkbox',
|
||||
'name': 'showhistory',
|
||||
'disabled': null
|
||||
}), ' ',
|
||||
E('label', { 'for': 'history-full' }), ' ',
|
||||
_('Keep the previous reply when sending a new USSD code.')
|
||||
]),
|
||||
'\xa0\xa0\xa0',
|
||||
E('label', { 'class': 'cbi-checkbox' }, [
|
||||
E('input', {
|
||||
'id': 'reverse-replies',
|
||||
'data-tooltip': _('View new reply from top'),
|
||||
'type': 'checkbox',
|
||||
'name': 'reversereplies',
|
||||
'disabled': true
|
||||
}), ' ',
|
||||
E('label', { 'for': 'reverse-replies' }), ' ',
|
||||
_('Turn over the replies.')
|
||||
])
|
||||
]),
|
||||
E('hr'),
|
||||
E('div', { 'class': 'right' }, [
|
||||
E('button', {
|
||||
'class': 'cbi-button cbi-button-remove',
|
||||
'id': 'clr',
|
||||
'click': ui.createHandlerFn(this, 'handleClear')
|
||||
}, [ _('Clear form') ]),
|
||||
'\xa0\xa0\xa0',
|
||||
E('button', {
|
||||
'class': 'cbi-button cbi-button-action important',
|
||||
'id': 'execute',
|
||||
'click': ui.createHandlerFn(this, 'handleGo')
|
||||
}, [ _('Send code') ]),
|
||||
]),
|
||||
E('p', _('Reply')),
|
||||
E('pre', { 'class': 'ussdcommand-output', 'style': 'display:none; border: 1px solid var(--border-color-medium); border-radius: 5px; font-family: monospace' }),
|
||||
|
||||
]);
|
||||
},
|
||||
|
||||
handleSaveApply: null,
|
||||
handleSave: null,
|
||||
handleReset: null
|
||||
})
|
||||
@@ -0,0 +1,369 @@
|
||||
'use strict';
|
||||
'require form';
|
||||
'require fs';
|
||||
'require view';
|
||||
'require uci';
|
||||
'require ui';
|
||||
'require tools.widgets as widgets'
|
||||
|
||||
/*
|
||||
Copyright 2022-2025 Rafał Wabik - IceG - From eko.one.pl forum
|
||||
|
||||
Licensed to the GNU General Public License v3.0.
|
||||
*/
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
return fs.list('/dev').then(function(devs) {
|
||||
return devs.filter(function(dev) {
|
||||
return dev.name.match(/^ttyUSB/) || dev.name.match(/^cdc-wdm/) || dev.name.match(/^ttyACM/) || dev.name.match(/^mhi_/) || dev.name.match(/^wwan/);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
render: function(devs) {
|
||||
let m, s, o;
|
||||
m = new form.Map('sms_tool_js', _('Configuration sms-tool'), _('Configuration panel for sms-tool and gui application.'));
|
||||
|
||||
s = m.section(form.TypedSection, 'sms_tool_js', '', null);
|
||||
s.anonymous = true;
|
||||
|
||||
//TAB SMS
|
||||
|
||||
s.tab('smstab' , _('SMS Settings'));
|
||||
s.anonymous = true;
|
||||
|
||||
o = s.taboption('smstab' , form.Value, 'readport', _('SMS reading port'),
|
||||
_('Select one of the available ttyUSBX ports.'));
|
||||
devs.sort((a, b) => a.name > b.name);
|
||||
devs.forEach(dev => o.value('/dev/' + dev.name));
|
||||
|
||||
o.placeholder = _('Please select a port');
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.taboption('smstab', form.ListValue, 'storage', _('Message storage area'),
|
||||
_('Messages are stored in a specific location (for example, on the SIM card or modem memory), but other areas may also be available depending on the type of device.'));
|
||||
o.value('SM', _('SIM card'));
|
||||
o.value('ME', _('Modem memory'));
|
||||
o.default = 'SM';
|
||||
|
||||
o = s.taboption('smstab', form.Flag, 'mergesms', _('Merge split messages'),
|
||||
_('Checking this option will make it easier to read the messages, but it will cause a discrepancy in the number of messages shown and received.')
|
||||
);
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.taboption('smstab' , form.ListValue, 'algorithm', _('Merge algorithm'),
|
||||
_(''));
|
||||
o.value('Simple', _('Simple (merge without sorting)'));
|
||||
o.value('Advanced', _('Advanced (merges with sorting)'));
|
||||
o.default = 'Advanced';
|
||||
o.depends('mergesms', '1');
|
||||
|
||||
o = s.taboption('smstab' , form.ListValue, 'direction', _('Direction of message merging'),
|
||||
_(''));
|
||||
o.value('Start', _('From beginning to end'));
|
||||
o.value('End', _('From end to beginning'));
|
||||
o.default = 'Start';
|
||||
o.depends('algorithm', 'Advanced');
|
||||
|
||||
o = s.taboption('smstab', form.Value, 'bnumber', _('Phone number to be blurred'),
|
||||
_('The last 5 digits of this number will be blurred.')
|
||||
);
|
||||
o.password = true;
|
||||
|
||||
o = s.taboption('smstab', form.Button, '_fsave');
|
||||
o.title = _('Save messages to a text file');
|
||||
o.description = _('This option allows to backup SMS messages or, for example, save messages that are not supported by the sms-tool.');
|
||||
o.inputtitle = _('Save as .txt file');
|
||||
o.onclick = function() {
|
||||
return uci.load('sms_tool_js').then(function() {
|
||||
let portES = (uci.get('sms_tool_js', '@sms_tool_js[0]', 'readport'));
|
||||
L.resolveDefault(fs.exec_direct('/usr/bin/sms_tool', [ '-d' , portES , '-f' , '%Y-%m-%d %H:%M' , 'recv' , '2>/dev/null']))
|
||||
.then(function(res) {
|
||||
if (res) {
|
||||
fs.write('/tmp/mysms.txt', res.trim().replace(/\r\n/g, '\n') + '\n');
|
||||
let fileName = 'mysms.txt';
|
||||
let filePath = '/tmp/' + fileName;
|
||||
|
||||
fs.stat(filePath)
|
||||
.then(function () {
|
||||
|
||||
if (confirm(_('Save sms to txt file?'))) {
|
||||
L.resolveDefault(fs.read_direct('/tmp/mysms.txt'), null).then(function (restxt) {
|
||||
if (restxt) {
|
||||
L.ui.showModal(_('Saving...'), [
|
||||
E('p', { 'class': 'spinning' }, _('Please wait.. Process of saving SMS message to a text file is in progress.'))
|
||||
]);
|
||||
let link = E('a', {
|
||||
'download': 'mysms.txt',
|
||||
'href': URL.createObjectURL(
|
||||
new Blob([ restxt ], { type: 'text/plain' })),
|
||||
});
|
||||
window.setTimeout(function() {
|
||||
link.click();
|
||||
URL.revokeObjectURL(link.href);
|
||||
L.hideModal();
|
||||
}, 2000).finally();
|
||||
} else {
|
||||
ui.addNotification(null, E('p', {}, _('Saving SMS messages to a file failed. Please try again.')));
|
||||
}
|
||||
}).catch(() => {
|
||||
ui.addNotification(null, E('p', {}, _('Download error') + ': ' + err.message));
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
o = s.taboption('smstab', form.Button, '_fdelete');
|
||||
o.title = _('Delete all messages');
|
||||
o.description = _("This option allows you to delete all SMS messages when they are not visible in the 'Received Messages' tab.");
|
||||
o.inputtitle = _('Delete all');
|
||||
o.onclick = function() {
|
||||
if (confirm(_('Delete all the messages?'))) {
|
||||
return uci.load('sms_tool_js').then(function() {
|
||||
let portFD = (uci.get('sms_tool_js', '@sms_tool_js[0]', 'readport'));
|
||||
fs.exec_direct('/usr/bin/sms_tool', [ '-d' , portFD , 'delete' , 'all' ]);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
o = s.taboption('smstab', form.Value, 'sendport', _('SMS sending port'),
|
||||
_("Select one of the available ttyUSBX ports."));
|
||||
devs.sort((a, b) => a.name > b.name);
|
||||
devs.forEach(dev => o.value('/dev/' + dev.name));
|
||||
|
||||
o.placeholder = _('Please select a port');
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.taboption('smstab', form.Value, 'pnumber', _('Prefix number'),
|
||||
_("The phone number should be preceded by the country prefix (for Poland it is 48, without '+'). If the number is 5, 4 or 3 characters, it is treated as 'short' and should not be preceded by a country prefix."));
|
||||
o.default = '48';
|
||||
o.validate = function(section_id, value) {
|
||||
|
||||
if (value.match(/^[0-9]+(?:\.[0-9]+)?$/))
|
||||
return true;
|
||||
|
||||
return _('Expect a decimal value');
|
||||
};
|
||||
|
||||
o = s.taboption('smstab', form.Flag, 'prefix', _('Add prefix to phone number'),
|
||||
_('Automatically add prefix to the phone number field.')
|
||||
);
|
||||
o.rmempty = false;
|
||||
//o.default = true;
|
||||
|
||||
o = s.taboption('smstab', form.Flag, 'sendingroup', _('Enable group messaging'),
|
||||
_("This option allows you to send one message to all contacts in the user's contact list."));
|
||||
o.rmempty = false;
|
||||
o.default = false;
|
||||
|
||||
o = s.taboption('smstab', form.Value, 'delay', _('Message sending delay'),
|
||||
_("[3 - 59] second(s) \
|
||||
<br /><br /><b>Important</b> \
|
||||
<br />Messages are sent without verification and confirmation delivery of the message. \
|
||||
Therefore, there is a risk of non-delivery of the message."));
|
||||
o.default = "3";
|
||||
o.rmempty = false;
|
||||
o.validate = function(section_id, value) {
|
||||
|
||||
if (value.match(/^[0-9]+(?:\.[0-9]+)?$/) && +value >= 3 && +value < 60)
|
||||
return true;
|
||||
|
||||
return _('Expect a decimal value between three and fifty-nine');
|
||||
};
|
||||
o.depends("sendingroup", "1");
|
||||
o.datatype = 'range(3, 59)';
|
||||
|
||||
o = s.taboption('smstab', form.Flag, 'information', _('Explanation of number and prefix'),
|
||||
_('In the tab for sending SMSes, show an explanation of the prefix and the correct phone number.')
|
||||
);
|
||||
o.rmempty = false;
|
||||
//o.default = true;
|
||||
|
||||
o = s.taboption('smstab', form.TextValue, '_tmp2', _('User contacts'),
|
||||
_("Each line must have the following format: 'Contact name;phone number'. For user convenience, the file is saved to the location <code>/etc/modem/phonebook.user</code>."));
|
||||
o.rows = 7;
|
||||
o.cfgvalue = function(section_id) {
|
||||
return fs.trimmed('/etc/modem/phonebook.user');
|
||||
};
|
||||
o.write = function(section_id, formvalue) {
|
||||
return fs.write('/etc/modem/phonebook.user', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
|
||||
};
|
||||
|
||||
//TAB USSD
|
||||
|
||||
s.tab('ussd', _('USSD Codes Settings'));
|
||||
s.anonymous = true;
|
||||
|
||||
o = s.taboption('ussd', form.Value, 'ussdport', _('USSD sending port'),
|
||||
_('Select one of the available ttyUSBX ports.'));
|
||||
devs.sort((a, b) => a.name > b.name);
|
||||
devs.forEach(dev => o.value('/dev/' + dev.name));
|
||||
|
||||
o.placeholder = _('Please select a port');
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.taboption('ussd', form.Flag, 'ussd', _('Sending USSD code in plain text'),
|
||||
_('Send the USSD code in plain text. Command is not being coded to the PDU.')
|
||||
);
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.taboption('ussd', form.Flag, 'pdu', _('Receive message without PDU decoding'),
|
||||
_('Receive and display the message without decoding it as a PDU.')
|
||||
);
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.taboption('ussd', form.ListValue, 'coding', _('PDU decoding scheme'));
|
||||
o.value('auto', _('Autodetect'));
|
||||
o.value('0', _('7Bit'));
|
||||
o.value('2', _('UCS2'));
|
||||
o.default = 'auto';
|
||||
|
||||
o = s.taboption('ussd', form.TextValue, '_tmp4', _('User USSD codes'),
|
||||
_("Each line must have the following format: 'Code description;code'. For user convenience, the file is saved to the location <code>/etc/modem/ussdcodes.user</code>."));
|
||||
o.rows = 7;
|
||||
o.cfgvalue = function(section_id) {
|
||||
return fs.trimmed('/etc/modem/ussdcodes.user');
|
||||
};
|
||||
o.write = function(section_id, formvalue) {
|
||||
return fs.write('/etc/modem/ussdcodes.user', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
|
||||
};
|
||||
|
||||
//TAB AT
|
||||
|
||||
s.tab('attab', _('AT Commands Settings'));
|
||||
s.anonymous = true;
|
||||
|
||||
o = s.taboption('attab' , form.Value, 'atport', _('AT commands sending port'),
|
||||
_('Select one of the available ttyUSBX ports.'));
|
||||
devs.sort((a, b) => a.name > b.name);
|
||||
devs.forEach(dev => o.value('/dev/' + dev.name));
|
||||
|
||||
o.placeholder = _('Please select a port');
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.taboption('attab' , form.TextValue, '_tmp6', _('User AT commands'),
|
||||
_("Each line must have the following format: 'At command description;AT command'. For user convenience, the file is saved to the location <code>/etc/modem/atcmmds.user</code>."));
|
||||
o.rows = 20;
|
||||
o.cfgvalue = function(section_id) {
|
||||
return fs.trimmed('/etc/modem/atcmmds.user');
|
||||
};
|
||||
o.write = function(section_id, formvalue) {
|
||||
return fs.write('/etc/modem/atcmmds.user', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
|
||||
};
|
||||
|
||||
//TAB INFO
|
||||
|
||||
s.tab('notifytab', _('Notification Settings'));
|
||||
s.anonymous = true;
|
||||
|
||||
o = s.taboption('notifytab', form.Flag, 'lednotify', _('Notify new messages'),
|
||||
_('The LED informs about a new message. Before activating this function, please config and save the SMS reading port, time to check SMS inbox and select the notification LED.')
|
||||
);
|
||||
o.rmempty = false;
|
||||
o.default = true;
|
||||
o.write = function(section_id, value) {
|
||||
|
||||
uci.load('sms_tool_js').then(function() {
|
||||
let storeL = (uci.get('sms_tool_js', '@sms_tool_js[0]', 'storage'));
|
||||
let portR = (uci.get('sms_tool_js', '@sms_tool_js[0]', 'readport'));
|
||||
let dsled = (uci.get('sms_tool_js', '@sms_tool_js[0]', 'ledtype'));
|
||||
|
||||
L.resolveDefault(fs.exec_direct('/usr/bin/sms_tool', [ '-s' , storeL , '-d' , portR , 'status' ]))
|
||||
.then(function(res) {
|
||||
if (res) {
|
||||
let total = res.substring(res.indexOf('total'));
|
||||
let t = total.replace ( /[^\d.]/g, '' );
|
||||
let used = res.substring(17, res.indexOf('total'));
|
||||
let u = used.replace ( /[^\d.]/g, '' );
|
||||
|
||||
let sections = uci.sections('sms_tool_js');
|
||||
let led = sections[0].smsled;
|
||||
|
||||
if (value == '1') {
|
||||
uci.set('sms_tool_js', '@sms_tool_js[0]', 'sms_count', L.toArray(u).join(' '));
|
||||
uci.set('sms_tool_js', '@sms_tool_js[0]', 'lednotify', "1");
|
||||
uci.save();
|
||||
fs.exec_direct('/sbin/new_cron_sync.sh');
|
||||
fs.exec_direct('/etc/init.d/my_new_sms', [ 'enable' ]);
|
||||
fs.exec('sleep 2');
|
||||
fs.exec_direct('/etc/init.d/my_new_sms', [ 'start' ]);
|
||||
}
|
||||
|
||||
if (value == '0') {
|
||||
uci.set('sms_tool_js', '@sms_tool_js[0]', 'lednotify', "0");
|
||||
uci.save();
|
||||
fs.exec_direct('/sbin/new_cron_sync.sh');
|
||||
fs.exec_direct('/etc/init.d/my_new_sms', [ 'stop' ]);
|
||||
fs.exec('sleep 2');
|
||||
fs.exec_direct('/etc/init.d/my_new_sms', [ 'disable' ]);
|
||||
fs.exec_direct('/etc/init.d/my_new_sms', [ 'disable' ]);
|
||||
|
||||
if (dsled == 'D') {
|
||||
fs.write('/sys/class/leds/'+led+'/brightness', '0');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return form.Flag.prototype.write.apply(this, [section_id, value]);
|
||||
};
|
||||
|
||||
o = s.taboption('notifytab', form.Value, 'checktime', _('Check inbox every minute(s)'),
|
||||
_('Specify how many minutes you want your inbox to be checked.'));
|
||||
o.default = '10';
|
||||
o.rmempty = false;
|
||||
o.validate = function(section_id, value) {
|
||||
|
||||
if (value.match(/^[0-9]+(?:\.[0-9]+)?$/) && +value >= 5 && +value < 60)
|
||||
return true;
|
||||
|
||||
return _('Expect a decimal value between five and fifty-nine');
|
||||
};
|
||||
o.datatype = 'range(5, 59)';
|
||||
|
||||
o = s.taboption('notifytab' , form.ListValue, 'prestart', _('Restart the inbox checking process every'),
|
||||
_('The process will restart at the selected time interval. This will eliminate the delay in checking your inbox.'));
|
||||
o.value('4', _('4h'));
|
||||
o.value('6', _('6h'));
|
||||
o.value('8', _('8h'));
|
||||
o.value('12', _('12h'));
|
||||
o.default = '6';
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.taboption('notifytab' , form.ListValue, 'ledtype',
|
||||
_('The diode is dedicated only to these notifications'),
|
||||
_("Select 'No' in case the router has only one LED or if the LED is multi-tasking. \
|
||||
<br /><br /><b>Important</b> \
|
||||
<br />This option requires LED to be defined in the system (if possible) to work properly. \
|
||||
This requirement applies when the diode supports multiple tasks."));
|
||||
o.value('S', _('No'));
|
||||
o.value('D', _('Yes'));
|
||||
o.default = 'D';
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.taboption('notifytab', form.ListValue, 'smsled',_('<abbr title="Light Emitting Diode">LED</abbr> Name'),
|
||||
_('Select the notification LED.'));
|
||||
o.load = function(section_id) {
|
||||
return L.resolveDefault(fs.list('/sys/class/leds'), []).then(L.bind(function(leds) {
|
||||
if(leds.length > 0) {
|
||||
leds.sort((a, b) => a.name > b.name);
|
||||
leds.forEach(e => o.value(e.name));
|
||||
}
|
||||
return this.super('load', [section_id]);
|
||||
}, this));
|
||||
};
|
||||
o.exclude = s.section;
|
||||
o.nocreate = true;
|
||||
o.optional = true;
|
||||
o.rmempty = true;
|
||||
|
||||
return m.render();
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user