🌴 Sync 2026-03-05 23:51:42
No files matched your search
@@ -0,0 +1,11 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=Information dashboard for 3G/LTE dongle
|
||||
LUCI_DEPENDS:=+modeminfo
|
||||
PKG_LICENSE:=GPLv3
|
||||
PKG_VERSION:=0.4.5
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
@@ -0,0 +1,83 @@
|
||||
# luci-app-modeminfo
|
||||
3G/LTE dongle information for OpenWrt LuCi
|
||||
|
||||
|
||||
luci-app-modeminfo is fork from https://github.com/IceG2020/luci-app-3ginfo
|
||||
|
||||
Supported devices:
|
||||
|
||||
- Quectel EC200T/EC21/EC25/EP06/EM12/EM160R-GL
|
||||
|
||||
- SimCom SIM7600E-H/SIM7906/A7600/A7906-M2
|
||||
|
||||
- STYX MG8224
|
||||
|
||||
- Huawei E3372 (LTE)/MU709/ME909
|
||||
|
||||
- Sierra Wireless EM7455/EM9191
|
||||
|
||||
- HP LT4220
|
||||
|
||||
- Dell DW5821e/DW5829e
|
||||
|
||||
- MEIGLink SLM750-R2/SLM820/SLM828
|
||||
|
||||
- MikroTik R11e-LTE/R11e-LTE6
|
||||
|
||||
- Fibocom NL668/NL678/L850/L860/NL952/FM150/FM190/FM350
|
||||
|
||||
- Gosuncnwelink GM510
|
||||
|
||||
- ThinkWill ML7820+
|
||||
|
||||
- Yuge CLM920
|
||||
|
||||
- ZTE MF823/MF823D
|
||||
|
||||
<details>
|
||||
<summary>Package contents:</summary>
|
||||
|
||||
|Package |Description |
|
||||
|:-------|:-----------|
|
||||
|luci-app-modeminfo |LuCI web interface |
|
||||
|modeminfo |common files |
|
||||
|modeminfo-qmi |Qualcomm MSM Interface support |
|
||||
|modeminfo-serial-quectel |Quectel modems support |
|
||||
|modeminfo-serial-telit |Telit LN940 (HP LT4220) modem support |
|
||||
|modeminfo-serial-huawei |Huawei MU709/ME909/E3372(stick mode, LTE only) modems support|
|
||||
|modeminfo-serial-sierra |Sierra EM7455/EM9191 modem support |
|
||||
|modeminfo-serial-simcom |SimCOM modems support |
|
||||
|modeminfo-serial-dell |Dell DW5821e/DW5829e modem support |
|
||||
|modeminfo-serial-fibocom |Fibocom LN668/NL678/NL952/FM150/FM190 modems support |
|
||||
|modeminfo-serial-xmm |Fibocom L850/L860/FM350 modems support |
|
||||
|modeminfo-serial-mikrotik |MikroTik R11e-LTE/R11e-LTE6 modems support |
|
||||
|modeminfo-serial-gosun |Gosuncnwelink GM510 support |
|
||||
|modeminfo-serial-tw |ThinkWill ML7820+ support |
|
||||
|modeminfo-serial-yuge |Yuge CLM920 support |
|
||||
|modeminfo-serial-meig |MEIGLink SLM750-R2/SLM820/SLM828 support |
|
||||
|modeminfo-serial-zte |ZTE MF823/MF823D support |
|
||||
|modeminfo-serial-styx |STYX MG8224 support |
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Screenshots</summary>
|
||||
|
||||
|
||||
* Overview page. Short network info.
|
||||
|
||||

|
||||
|
||||
* Modeminfo index page. Verbose network info.
|
||||
|
||||

|
||||
|
||||
* Modeminfo hardware page.
|
||||
|
||||

|
||||
|
||||
* Modeminfo setup page.
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
'use strict';
|
||||
'require baseclass';
|
||||
'require form';
|
||||
'require fs';
|
||||
'require view';
|
||||
'require ui';
|
||||
'require uci';
|
||||
'require poll';
|
||||
'require dom';
|
||||
'require tools.widgets as widgets';
|
||||
|
||||
|
||||
/*
|
||||
Copyright Konstantine Shevlakov <shevlakov@132lan.ru> 2023
|
||||
|
||||
Licensed to the GNU General Public License v3.0.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
return view.extend({
|
||||
|
||||
load: function(data) {
|
||||
return L.resolveDefault(fs.exec_direct('/usr/bin/modeminfo'));
|
||||
},
|
||||
|
||||
polldata: poll.add(function() {
|
||||
return L.resolveDefault(fs.exec_direct('/usr/bin/modeminfo')).then(function(res) {
|
||||
var json = JSON.parse(res);
|
||||
if (!json || !json.modem || !Array.isArray(json.modem)) return;
|
||||
for (var i = 0; i < json.modem.length; i++) {
|
||||
if (document.getElementById('device'+i)) {
|
||||
var view = document.getElementById('device'+i);
|
||||
if (json.modem[i].device == '--') {
|
||||
view = document.getElementById('--');
|
||||
} else {
|
||||
view.innerHTML = String.format(json.modem[i].device);
|
||||
}
|
||||
}
|
||||
if (document.getElementById('firmware'+i)) {
|
||||
var view = document.getElementById('firmware'+i);
|
||||
if (json.modem[i].firmware == '--') {
|
||||
view = document.getElementById('--');
|
||||
} else {
|
||||
view.innerHTML = String.format(json.modem[i].firmware);
|
||||
}
|
||||
}
|
||||
if (document.getElementById('imsi'+i)) {
|
||||
var view = document.getElementById('imsi'+i);
|
||||
if (json.modem[i].imsi == '--') {
|
||||
view = document.getElementById('--');
|
||||
} else {
|
||||
view.innerHTML = String.format(json.modem[i].imsi);
|
||||
}
|
||||
}
|
||||
if (document.getElementById('iccid'+i)) {
|
||||
var view = document.getElementById('iccid'+i);
|
||||
if (json.modem[i].iccid == '--') {
|
||||
view = document.getElementById('--');
|
||||
} else {
|
||||
view.innerHTML = String.format(json.modem[i].iccid);
|
||||
}
|
||||
}
|
||||
|
||||
if (document.getElementById('imei'+i)) {
|
||||
var view = document.getElementById('imei'+i);
|
||||
if (json.modem[i].imei == '--') {
|
||||
view = document.getElementById('--');
|
||||
} else {
|
||||
view.innerHTML = String.format(json.modem[i].imei);
|
||||
}
|
||||
}
|
||||
|
||||
if (document.getElementById('chiptemp'+i)) {
|
||||
var view = document.getElementById('chiptemp'+i);
|
||||
if (json.modem[i].chiptemp == '--') {
|
||||
view = document.getElementById('--');
|
||||
} else {
|
||||
view.innerHTML = String.format(json.modem[i].chiptemp+' °C');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
}),
|
||||
|
||||
render: function(data){
|
||||
|
||||
var m, s, o;
|
||||
m = new form.Map('modeminfo', _('Modeminfo: Hardware'), _('Hardware and sim-card info.'));
|
||||
s = m.section(form.TypedSection, 'general', null);
|
||||
var json = JSON.parse(data);
|
||||
// for future use
|
||||
/*
|
||||
var vendors = [];
|
||||
var duplicate_modem_index = 1;
|
||||
json.modem.forEach(obj => {
|
||||
const device = obj.device;
|
||||
if (!vendors.includes(device)) {
|
||||
vendors.push(device);
|
||||
} else {
|
||||
vendors.push(device+" ("+duplicate_modem_index+")");
|
||||
duplicate_modem_index++;
|
||||
}
|
||||
});
|
||||
*/
|
||||
for (var i = 0; i < json.modem.length; i++) {
|
||||
let device = 'device'+i;
|
||||
let firmware = 'firmware'+i;
|
||||
let imsi = 'imsi'+i;
|
||||
let iccid = 'iccid'+i;
|
||||
let imei = 'imei'+i;
|
||||
let chiptemp = 'chiptemp'+i;
|
||||
let m = i+1;
|
||||
if ( json.modem.length > 1 ) {
|
||||
s.tab('modem'+i, _('Modem')+' '+m);
|
||||
o = s.taboption('modem'+i, form.HiddenValue, 'generic');
|
||||
} else {
|
||||
o = s.option(form.HiddenValue, 'generic');
|
||||
}
|
||||
o.render = L.bind(function(data){
|
||||
return (
|
||||
E('div', {}, [
|
||||
E('h3', { 'class': 'data-tab' }),
|
||||
E('div', { 'class': 'cbi-section', 'data-title': 'modem'+i }, [
|
||||
E('table', { 'class': 'table' }, [
|
||||
E('tr', { 'class': 'tr cbi-rowstyle-2' }, [
|
||||
E('td', { 'class': 'td left', 'width': '50%' }, [ _('Device')]),
|
||||
E('td', { 'class': 'td left', 'id': device }, [ '--' ]),
|
||||
]),
|
||||
E('tr', { 'class': 'tr cbi-rowstyle-1' }, [
|
||||
E('td', { 'class': 'td left', 'width': '50%' }, [ _('Firmware')]),
|
||||
E('td', { 'class': 'td left', 'id': firmware }, [ '--' ]),
|
||||
]),
|
||||
E('tr', { 'class': 'tr cbi-rowstyle-2' }, [
|
||||
E('td', { 'class': 'td left', 'width': '50%' }, [ _('IMSI')]),
|
||||
E('td', { 'class': 'td left', 'id': imsi }, [ '--' ]),
|
||||
]),
|
||||
E('tr', { 'class': 'tr cbi-rowstyle-1' }, [
|
||||
E('td', { 'class': 'td left', 'width': '50%' }, [ _('ICCID')]),
|
||||
E('td', { 'class': 'td left', 'id': iccid }, [ '--' ]),
|
||||
]),
|
||||
E('tr', { 'class': 'tr cbi-rowstyle-2' }, [
|
||||
E('td', { 'class': 'td left', 'width': '50%' }, [ _('IMEI')]),
|
||||
E('td', { 'class': 'td left', 'id': imei }, [ '--' ]),
|
||||
]),
|
||||
E('tr', { 'class': 'tr cbi-rowstyle-1' }, [
|
||||
E('td', { 'class': 'td left', 'width': '50%' }, [ _('Chiptemp')]),
|
||||
E('td', { 'class': 'td left', 'id': chiptemp }, [ '--' ]),
|
||||
])
|
||||
])
|
||||
]),
|
||||
]
|
||||
)
|
||||
)}, o, this.polldata);
|
||||
o.anonymous = true;
|
||||
o.rmempty = true;
|
||||
};
|
||||
s.anonymous = true;
|
||||
return m.render();
|
||||
|
||||
},
|
||||
handleSaveApply: null,
|
||||
handleSave: null,
|
||||
handleReset: null
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
<svg height="32" width="32" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="b"><stop offset="0" stop-color="#aaa"/><stop offset="1" stop-color="#f0f0f0"/></linearGradient><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="76" x2="76" xlink:href="#b" y1="14" y2="-66"/><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="56" x2="56" xlink:href="#b" y1="14" y2="-50"/><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="44" x2="44" xlink:href="#b" y1="14" y2="-34"/><linearGradient id="f" gradientUnits="userSpaceOnUse" x1="16" x2="16" xlink:href="#b" y1="14" y2="-18"/><linearGradient id="g" gradientUnits="userSpaceOnUse" x1="78" x2="78" xlink:href="#a" y1="-66" y2="6.027772"/><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="19" x2="19" xlink:href="#a" y1="-18" y2="14.140317"/><linearGradient id="i" gradientUnits="userSpaceOnUse" x1="37" x2="37" xlink:href="#a" y1="-34" y2="14.010415"/><linearGradient id="j" gradientUnits="userSpaceOnUse" x1="57" x2="57" xlink:href="#a" y1="-50" y2="14.007812"/><g transform="translate(0 74)"><path d="m74-67.96875c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v24c0 3.827486 3.141264 6.96875 6.96875 6.96875h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c3.827486 0 6.96875-3.141264 6.96875-6.96875v-72c0-3.827486-3.141264-6.96875-6.96875-6.96875z" opacity=".08"/><path d="m74-66.96875c-3.283091 0-5.96875 2.685659-5.96875 5.96875v72c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-72c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v56c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-56c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v40c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-40c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v24c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-24c0-3.283091-2.685659-5.96875-5.96875-5.96875z" opacity=".1"/><path d="m74-66.03125c-2.763365 0-5.03125 2.267885-5.03125 5.03125v72c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-72c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v56c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-56c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v40c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-40c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v24c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-24c0-2.763365-2.267885-5.03125-5.03125-5.03125z" opacity=".15"/><path d="m74-65c-2.216 0-4 1.784-4 4v72c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-72c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v56c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-56c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v40c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-40c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v24c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-24c0-2.216-1.784-4-4-4z" opacity=".3"/><rect fill="url(#c)" height="80" rx="4" width="16" x="70" y="-66"/><rect fill="url(#d)" height="64" rx="4" width="16" x="50" y="-50"/><rect fill="url(#e)" height="48" rx="4" width="16" x="30" y="-34"/><rect fill="url(#f)" height="32" rx="4" width="16" x="10" y="-18"/><path d="m74-66c-2.216 0-4 1.784-4 4v72c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-72c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 1.333678 3.03125 3.03125v72c0 1.273179-.75249 2.326579-1.84375 2.78125 1.628072-.506247 2.8125-1.982301 2.8125-3.78125v-72c0-2.216-1.784-4-4-4z" fill="url(#g)" opacity=".6"/><path d="m54-50c-2.216 0-4 1.784-4 4v56c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-56c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 1.333678 3.03125 3.03125v56c0 1.273179-.75249 2.326579-1.84375 2.78125 1.62807Line truncated
|
||||
|
After Width: | Height: | Size: 5.7 KiB |
@@ -0,0 +1 @@
|
||||
<svg height="32" width="32" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="b"><stop offset="0" stop-color="#aaa"/><stop offset="1" stop-color="#f0f0f0"/></linearGradient><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="76" x2="76" xlink:href="#b" y1="14" y2="-66"/><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="56" x2="56" xlink:href="#b" y1="14" y2="-50"/><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="44" x2="44" xlink:href="#b" y1="14" y2="-34"/><linearGradient id="f" gradientUnits="userSpaceOnUse" x1="16" x2="16" y1="14" y2="-18"><stop offset="0" stop-color="#395d93"/><stop offset="1" stop-color="#6e92c7"/></linearGradient><linearGradient id="g" gradientUnits="userSpaceOnUse" x1="78" x2="78" xlink:href="#a" y1="-66" y2="6.027772"/><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="19" x2="19" xlink:href="#a" y1="-18" y2="14.140317"/><linearGradient id="i" gradientUnits="userSpaceOnUse" x1="37" x2="37" xlink:href="#a" y1="-34" y2="14.010415"/><linearGradient id="j" gradientUnits="userSpaceOnUse" x1="57" x2="57" xlink:href="#a" y1="-50" y2="14.007812"/><g transform="translate(0 74)"><path d="m74-67.96875c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v24c0 3.827486 3.141264 6.96875 6.96875 6.96875h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c3.827486 0 6.96875-3.141264 6.96875-6.96875v-72c0-3.827486-3.141264-6.96875-6.96875-6.96875z" opacity=".08"/><path d="m74-66.96875c-3.283091 0-5.96875 2.685659-5.96875 5.96875v72c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-72c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v56c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-56c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v40c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-40c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v24c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-24c0-3.283091-2.685659-5.96875-5.96875-5.96875z" opacity=".1"/><path d="m74-66.03125c-2.763365 0-5.03125 2.267885-5.03125 5.03125v72c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-72c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v56c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-56c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v40c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-40c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v24c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-24c0-2.763365-2.267885-5.03125-5.03125-5.03125z" opacity=".15"/><path d="m74-65c-2.216 0-4 1.784-4 4v72c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-72c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v56c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-56c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v40c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-40c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v24c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-24c0-2.216-1.784-4-4-4z" opacity=".3"/><rect fill="url(#c)" height="80" rx="4" width="16" x="70" y="-66"/><rect fill="url(#d)" height="64" rx="4" width="16" x="50" y="-50"/><rect fill="url(#e)" height="48" rx="4" width="16" x="30" y="-34"/><rect fill="url(#f)" height="32" rx="4" width="16" x="10" y="-18"/><path d="m74-66c-2.216 0-4 1.784-4 4v72c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-72c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 1.333678 3.03125 3.03125v72c0 1.273179-.75249 2.326579-1.84375 2.78125 1.628072-.506247 2.8125-1.982301 2.8125-3.78125v-72c0-2.216-1.784-4-4-4z" fill="url(#g)" opacity=".6"/><path d="m54-50c-2.216 0-4 1.784-4 4v56c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-56c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 Line truncated
|
||||
|
After Width: | Height: | Size: 5.8 KiB |
@@ -0,0 +1 @@
|
||||
<svg height="32" width="32" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="b"><stop offset="0" stop-color="#395d93"/><stop offset="1" stop-color="#6e92c7"/></linearGradient><linearGradient id="c"><stop offset="0" stop-color="#aaa"/><stop offset="1" stop-color="#f0f0f0"/></linearGradient><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="76" x2="76" xlink:href="#c" y1="14" y2="-66"/><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="56" x2="56" xlink:href="#c" y1="14" y2="-50"/><linearGradient id="f" gradientUnits="userSpaceOnUse" x1="44" x2="44" xlink:href="#b" y1="14" y2="-34"/><linearGradient id="g" gradientUnits="userSpaceOnUse" x1="16" x2="16" xlink:href="#b" y1="14" y2="-18"/><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="78" x2="78" xlink:href="#a" y1="-66" y2="6.027772"/><linearGradient id="i" gradientUnits="userSpaceOnUse" x1="19" x2="19" xlink:href="#a" y1="-18" y2="14.140317"/><linearGradient id="j" gradientUnits="userSpaceOnUse" x1="37" x2="37" xlink:href="#a" y1="-34" y2="14.010415"/><linearGradient id="k" gradientUnits="userSpaceOnUse" x1="57" x2="57" xlink:href="#a" y1="-50" y2="14.007812"/><g transform="translate(0 74)"><path d="m74-67.96875c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v24c0 3.827486 3.141264 6.96875 6.96875 6.96875h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c3.827486 0 6.96875-3.141264 6.96875-6.96875v-72c0-3.827486-3.141264-6.96875-6.96875-6.96875z" opacity=".08"/><path d="m74-66.96875c-3.283091 0-5.96875 2.685659-5.96875 5.96875v72c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-72c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v56c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-56c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v40c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-40c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v24c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-24c0-3.283091-2.685659-5.96875-5.96875-5.96875z" opacity=".1"/><path d="m74-66.03125c-2.763365 0-5.03125 2.267885-5.03125 5.03125v72c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-72c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v56c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-56c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v40c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-40c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v24c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-24c0-2.763365-2.267885-5.03125-5.03125-5.03125z" opacity=".15"/><path d="m74-65c-2.216 0-4 1.784-4 4v72c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-72c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v56c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-56c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v40c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-40c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v24c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-24c0-2.216-1.784-4-4-4z" opacity=".3"/><rect fill="url(#d)" height="80" rx="4" width="16" x="70" y="-66"/><rect fill="url(#e)" height="64" rx="4" width="16" x="50" y="-50"/><rect fill="url(#f)" height="48" rx="4" width="16" x="30" y="-34"/><rect fill="url(#g)" height="32" rx="4" width="16" x="10" y="-18"/><path d="m74-66c-2.216 0-4 1.784-4 4v72c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-72c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 1.333678 3.03125 3.03125v72c0 1.273179-.75249 2.326579-1.84375 2.78125 1.628072-.506247 2.8125-1.982301 2.8125-3.78125v-72c0-2.216-1.784-4-4-4z" fill="url(#h)" opacity=".6"/><path d="m54-50c-2.216 0-4 1.784-4 4v56c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-56c0-1.697572 1.333678-3.031Line truncated
|
||||
|
After Width: | Height: | Size: 5.8 KiB |
@@ -0,0 +1 @@
|
||||
<svg height="32" width="32" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="b"><stop offset="0" stop-color="#395d93"/><stop offset="1" stop-color="#6e92c7"/></linearGradient><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="76" x2="76" y1="14" y2="-66"><stop offset="0" stop-color="#aaa"/><stop offset="1" stop-color="#f0f0f0"/></linearGradient><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="56" x2="56" xlink:href="#b" y1="14" y2="-50"/><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="44" x2="44" xlink:href="#b" y1="14" y2="-34"/><linearGradient id="f" gradientUnits="userSpaceOnUse" x1="16" x2="16" xlink:href="#b" y1="14" y2="-18"/><linearGradient id="g" gradientUnits="userSpaceOnUse" x1="78" x2="78" xlink:href="#a" y1="-66" y2="6.027772"/><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="19" x2="19" xlink:href="#a" y1="-18" y2="14.140317"/><linearGradient id="i" gradientUnits="userSpaceOnUse" x1="37" x2="37" xlink:href="#a" y1="-34" y2="14.010415"/><linearGradient id="j" gradientUnits="userSpaceOnUse" x1="57" x2="57" xlink:href="#a" y1="-50" y2="14.007812"/><g transform="translate(0 74)"><path d="m74-67.96875c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v24c0 3.827486 3.141264 6.96875 6.96875 6.96875h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c3.827486 0 6.96875-3.141264 6.96875-6.96875v-72c0-3.827486-3.141264-6.96875-6.96875-6.96875z" opacity=".08"/><path d="m74-66.96875c-3.283091 0-5.96875 2.685659-5.96875 5.96875v72c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-72c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v56c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-56c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v40c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-40c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v24c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-24c0-3.283091-2.685659-5.96875-5.96875-5.96875z" opacity=".1"/><path d="m74-66.03125c-2.763365 0-5.03125 2.267885-5.03125 5.03125v72c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-72c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v56c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-56c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v40c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-40c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v24c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-24c0-2.763365-2.267885-5.03125-5.03125-5.03125z" opacity=".15"/><path d="m74-65c-2.216 0-4 1.784-4 4v72c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-72c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v56c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-56c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v40c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-40c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v24c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-24c0-2.216-1.784-4-4-4z" opacity=".3"/><rect fill="url(#c)" height="80" rx="4" width="16" x="70" y="-66"/><rect fill="url(#d)" height="64" rx="4" width="16" x="50" y="-50"/><rect fill="url(#e)" height="48" rx="4" width="16" x="30" y="-34"/><rect fill="url(#f)" height="32" rx="4" width="16" x="10" y="-18"/><path d="m74-66c-2.216 0-4 1.784-4 4v72c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-72c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 1.333678 3.03125 3.03125v72c0 1.273179-.75249 2.326579-1.84375 2.78125 1.628072-.506247 2.8125-1.982301 2.8125-3.78125v-72c0-2.216-1.784-4-4-4z" fill="url(#g)" opacity=".6"/><path d="m54-50c-2.216 0-4 1.784-4 4v56c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-56c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 Line truncated
|
||||
|
After Width: | Height: | Size: 5.8 KiB |
@@ -0,0 +1 @@
|
||||
<svg height="32" width="32" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="b"><stop offset="0" stop-color="#395d93"/><stop offset="1" stop-color="#6e92c7"/></linearGradient><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="76" x2="76" xlink:href="#b" y1="14" y2="-66"/><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="56" x2="56" xlink:href="#b" y1="14" y2="-50"/><linearGradient id="e" gradientUnits="userSpaceOnUse" x1="44" x2="44" xlink:href="#b" y1="14" y2="-34"/><linearGradient id="f" gradientUnits="userSpaceOnUse" x1="16" x2="16" xlink:href="#b" y1="14" y2="-18"/><linearGradient id="g" gradientUnits="userSpaceOnUse" x1="78" x2="78" xlink:href="#a" y1="-66" y2="6.027772"/><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="19" x2="19" xlink:href="#a" y1="-18" y2="14.140317"/><linearGradient id="i" gradientUnits="userSpaceOnUse" x1="37" x2="37" xlink:href="#a" y1="-34" y2="14.010415"/><linearGradient id="j" gradientUnits="userSpaceOnUse" x1="57" x2="57" xlink:href="#a" y1="-50" y2="14.007812"/><g transform="translate(0 74)"><path d="m74-67.96875c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v11.28125c-1.274027-1.358769-3.036218-2.25-5.03125-2.25h-8c-3.827486 0-6.96875 3.141264-6.96875 6.96875v24c0 3.827486 3.141264 6.96875 6.96875 6.96875h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c2.611074 0 4.807585-1.51241 6-3.65625 1.192415 2.14384 3.388926 3.65625 6 3.65625h8c3.827486 0 6.96875-3.141264 6.96875-6.96875v-72c0-3.827486-3.141264-6.96875-6.96875-6.96875z" opacity=".08"/><path d="m74-66.96875c-3.283091 0-5.96875 2.685659-5.96875 5.96875v72c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-72c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v56c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-56c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v40c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-40c0-3.283091-2.685659-5.96875-5.96875-5.96875zm-20 16c-3.283091 0-5.96875 2.685659-5.96875 5.96875v24c0 3.283091 2.685659 5.96875 5.96875 5.96875h8c3.283091 0 5.96875-2.685659 5.96875-5.96875v-24c0-3.283091-2.685659-5.96875-5.96875-5.96875z" opacity=".1"/><path d="m74-66.03125c-2.763365 0-5.03125 2.267885-5.03125 5.03125v72c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-72c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v56c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-56c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v40c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-40c0-2.763365-2.267885-5.03125-5.03125-5.03125zm-20 16c-2.763365 0-5.03125 2.267885-5.03125 5.03125v24c0 2.763365 2.267885 5.03125 5.03125 5.03125h8c2.763365 0 5.03125-2.267885 5.03125-5.03125v-24c0-2.763365-2.267885-5.03125-5.03125-5.03125z" opacity=".15"/><path d="m74-65c-2.216 0-4 1.784-4 4v72c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-72c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v56c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-56c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v40c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-40c0-2.216-1.784-4-4-4zm-20 16c-2.216 0-4 1.784-4 4v24c0 2.216 1.784 4 4 4h8c2.216 0 4-1.784 4-4v-24c0-2.216-1.784-4-4-4z" opacity=".3"/><rect fill="url(#c)" height="80" rx="4" width="16" x="70" y="-66"/><rect fill="url(#d)" height="64" rx="4" width="16" x="50" y="-50"/><rect fill="url(#e)" height="48" rx="4" width="16" x="30" y="-34"/><rect fill="url(#f)" height="32" rx="4" width="16" x="10" y="-18"/><path d="m74-66c-2.216 0-4 1.784-4 4v72c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-72c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 1.333678 3.03125 3.03125v72c0 1.273179-.75249 2.326579-1.84375 2.78125 1.628072-.506247 2.8125-1.982301 2.8125-3.78125v-72c0-2.216-1.784-4-4-4z" fill="url(#g)" opacity=".6"/><path d="m54-50c-2.216 0-4 1.784-4 4v56c0 1.798949 1.184428 3.275003 2.8125 3.78125-1.09126-.454671-1.84375-1.508071-1.84375-2.78125v-56c0-1.697572 1.333678-3.03125 3.03125-3.03125h8c1.697572 0 3.03125 1.333678 3.03125 3.03125v56c0 1.273179-.75249 2.326579-1.84375 2.78125 1.62Line truncated
|
||||
|
After Width: | Height: | Size: 5.7 KiB |
@@ -0,0 +1,472 @@
|
||||
'use strict';
|
||||
'require baseclass';
|
||||
'require form';
|
||||
'require fs';
|
||||
'require view';
|
||||
'require ui';
|
||||
'require uci';
|
||||
'require poll';
|
||||
'require dom';
|
||||
'require tools.widgets as widgets';
|
||||
|
||||
|
||||
/*
|
||||
Copyright Konstantine Shevlakov <shevlakov@132lan.ru> 2023
|
||||
|
||||
Licensed to the GNU General Public License v3.0.
|
||||
|
||||
*/
|
||||
|
||||
const REGISTERED_STATUSES = [1, 6, 9];
|
||||
const ROAMING_STATUSES = [3, 5, 7, 10];
|
||||
|
||||
|
||||
return view.extend({
|
||||
|
||||
load: function(data) {
|
||||
return L.resolveDefault(fs.exec_direct('/usr/bin/modeminfo'), '{"modem": []}');
|
||||
},
|
||||
|
||||
polldata: poll.add(function() {
|
||||
return L.resolveDefault(fs.exec_direct('/usr/bin/modeminfo'), '{"modem": []}').then(function(res) {
|
||||
var json = JSON.parse(res);
|
||||
if (!json || !json.modem || !Array.isArray(json.modem)) return;
|
||||
for (var i = 0; i < json.modem.length; i++) {
|
||||
// progressbar cellular metric
|
||||
const progressConfig = {
|
||||
rssi: {
|
||||
selector: '#rssi', min: -110, max: -50,
|
||||
calc: (vn, mn) => Math.floor(100 * (1 - (-50 - vn) / (-50 - mn)))
|
||||
},
|
||||
rsrp: {
|
||||
selector: '#rsrp', min: -140, max: -50,
|
||||
calc: (vn, mn) => Math.floor(120 * (1 - (-50 - vn) / (-70 - mn)))
|
||||
},
|
||||
sinr: {
|
||||
selector: '#sinr', min: -20, max: 30,
|
||||
calc: (vn, mn) => Math.floor(100 - (100 * (1 - ((mn - vn) / (mn - 30)))))
|
||||
},
|
||||
rsrq: {
|
||||
selector: '#rsrq', min: -20, max: 0,
|
||||
calc: (vn, mn) => Math.floor(115 - (100 / mn) * vn)
|
||||
},
|
||||
ecio: {
|
||||
selector: '#sinr', min: -24, max: 0,
|
||||
calc: (vn, mn) => Math.floor(100 - (100 / mn) * vn)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function updateProgressBar(type, value, max, i) {
|
||||
const config = progressConfig[type];
|
||||
if (!config) return;
|
||||
|
||||
const pg = document.querySelector(`${config.selector}${i}`);
|
||||
if (!pg) return;
|
||||
|
||||
const vn = Math.max(config.min, Math.min(config.max, parseInt(value) || 0));
|
||||
const mn = parseInt(max) || 100;
|
||||
const pc = config.calc(vn, mn);
|
||||
|
||||
pg.firstElementChild.style.width = `${pc}%`;
|
||||
pg.style.width = '%d%%';
|
||||
pg.firstElementChild.style.animationDirection = "reverse";
|
||||
pg.setAttribute('title', '%s'.format(value));
|
||||
}
|
||||
|
||||
function formatDistance(dist) {
|
||||
if (!dist || dist === "--" || dist === "" || dist === "0.00") {
|
||||
return '';
|
||||
}
|
||||
return ' ~' + dist + ' km';
|
||||
}
|
||||
|
||||
function formatModemStatus(modem, icon, reg) {
|
||||
var rg = parseInt(modem.reg) || 0;
|
||||
var p = modem.csq_per || 0;
|
||||
var cops = modem.cops || '--';
|
||||
var color = modem.csq_col || '#000000';
|
||||
|
||||
var distanceHtml = formatDistance(modem.distance);
|
||||
var iconHtml = icon ? '<img class="modem-signal-icon" src="' + icon + '"/>' : '';
|
||||
|
||||
var percentWithColor = p + '%';
|
||||
if (REGISTERED_STATUSES.includes(rg)) {
|
||||
return '<span class="ifacebadge">' + cops + ' ' + iconHtml +
|
||||
' <b style="color:' + color + '">' + percentWithColor + '</b>' +
|
||||
distanceHtml + '</span>';
|
||||
} else if (ROAMING_STATUSES.includes(rg)) {
|
||||
return '<span class="ifacebadge">' + cops + ' (' + reg + ') ' + iconHtml +
|
||||
' <b style="color:' + color + '">' + percentWithColor + '</b>' +
|
||||
distanceHtml + '</span>';
|
||||
} else {
|
||||
return '<span class="ifacebadge">' + (reg || '--') + '</span>';
|
||||
}
|
||||
}
|
||||
|
||||
// icon signal strength
|
||||
var icn;
|
||||
|
||||
var signalIcons = [
|
||||
{ max: -1, icn: 'signal-000-000.svg' },
|
||||
{ max: 0, icn: 'signal-000-000.svg' },
|
||||
{ max: 10, icn: 'signal-000-000.svg' },
|
||||
{ max: 25, icn: 'signal-000-025.svg' },
|
||||
{ max: 50, icn: 'signal-025-050.svg' },
|
||||
{ max: 75, icn: 'signal-050-075.svg' },
|
||||
{ max: Infinity, icn: 'signal-075-100.svg' }
|
||||
];
|
||||
|
||||
var p = json.modem[i].csq_per || 0;
|
||||
|
||||
var { icn } = signalIcons.find(({ max }) => p <= max);
|
||||
var icon = L.resource(`view/modem/icons/${icn}`);
|
||||
|
||||
// Registration Status
|
||||
var regStatuses = new Map([
|
||||
[0, _('No Registration')],
|
||||
[2, _('Searching')], [8, _('Searching')],
|
||||
[3, _('Denied')],
|
||||
[4, _('Unknown')],
|
||||
[5, _('Roaming')], [7, _('Roaming')], [10, _('Roaming')]
|
||||
]);
|
||||
|
||||
var rg = Number(json.modem[i].reg);
|
||||
var reg = regStatuses.get(rg) || _('No Data');
|
||||
|
||||
// frequency band calculator
|
||||
var offset, band, bw, frdl, frul;
|
||||
var netmode = (json.modem[i].mode)
|
||||
var rfcn = (json.modem[i].arfcn)
|
||||
if (netmode === "LTE") {
|
||||
// list LTE-bans
|
||||
var lteBands = [
|
||||
{ min: 0, max: 599, frdl: 2110, frul: 1920, offset: 0, band: "1" },
|
||||
{ min: 600, max: 1199, frdl: 1930, frul: 1850, offset: 600, band: "2" },
|
||||
{ min: 1200, max: 1949, frdl: 1805, frul: 1710, offset: 1200, band: "3" },
|
||||
{ min: 1950, max: 2399, frdl: 2110, frul: 1710, offset: 1950, band: "4" },
|
||||
{ min: 2400, max: 2469, frdl: 869, frul: 824, offset: 2400, band: "5" },
|
||||
{ min: 2750, max: 3449, frdl: 2620, frul: 2500, offset: 2750, band: "7" },
|
||||
{ min: 3450, max: 3799, frdl: 925, frul: 880, offset: 3450, band: "8" },
|
||||
{ min: 6150, max: 6449, frdl: 791, frul: 832, offset: 6150, band: "20" },
|
||||
{ min: 9210, max: 9659, frdl: 758, frul: 703, offset: 9210, band: "28" },
|
||||
{ min: 9870, max: 9919, frdl: 452.5, frul: 462.5, offset: 9870, band: "31" },
|
||||
{ min: 37750, max: 38249, frdl: 2570, frul: 2570, offset: 37750, band: "38" },
|
||||
{ min: 38650, max: 39649, frdl: 2300, frul: 2300, offset: 38650, band: "40" },
|
||||
{ min: 39650, max: 41589, frdl: 2496, frul: 2496, offset: 39650, band: "41" }
|
||||
];
|
||||
|
||||
var bandConfig = lteBands.find(b => rfcn >= b.min && rfcn <= b.max) || {
|
||||
frdl: 0, frul: 0, offset: 0, band: rfcn
|
||||
};
|
||||
({ frdl, frul, offset, band } = bandConfig);
|
||||
|
||||
// Bandwidth channel (bw)
|
||||
var bandwidths = [1.4, 3, 5, 10, 15, 20];
|
||||
var bw = bandwidths[json.modem[i].bwdl] || "";
|
||||
|
||||
// Calc frequency
|
||||
var dlfreq = frdl + (rfcn - offset) / 10;
|
||||
var ulfreq = frul + (rfcn - offset) / 10;
|
||||
} else {
|
||||
var nonLteBands = [
|
||||
{
|
||||
condition: (rfcn) => rfcn >= 10562 && rfcn <= 10838,
|
||||
calc: (rfcn) => ({ offset: 950, dlfreq: rfcn / 5, ulfreq: (rfcn - 950) / 5, band: "IMT2100" })
|
||||
},
|
||||
{
|
||||
condition: (rfcn) => rfcn >= 2937 && rfcn <= 3088,
|
||||
calc: (rfcn) => ({ frul: 925, offset: 340, ulfreq: 340 + (rfcn / 5), dlfreq: (340 + (rfcn / 5)) - 45, band: "UMTS900" })
|
||||
},
|
||||
{
|
||||
condition: (rfcn) => rfcn >= 955 && rfcn <= 1023,
|
||||
calc: (rfcn) => ({ frul: 890, ulfreq: 890 + ((rfcn - 1024) / 5), dlfreq: (890 + ((rfcn - 1024) / 5)) + 45, band: "DSC900" })
|
||||
},
|
||||
{
|
||||
condition: (rfcn) => rfcn >= 512 && rfcn <= 885,
|
||||
calc: (rfcn) => ({ frul: 1710, ulfreq: 1710 + ((rfcn - 512) / 5), dlfreq: (1710 + ((rfcn - 512) / 5)) + 95, band: "DCS1800" })
|
||||
},
|
||||
{
|
||||
condition: (rfcn) => rfcn >= 1 && rfcn <= 124,
|
||||
calc: (rfcn) => ({ frul: 890, ulfreq: 890 + (rfcn / 5), dlfreq: (890 + (rfcn / 5)) + 45, band: "GSM900" })
|
||||
}
|
||||
];
|
||||
|
||||
var bandConfig = nonLteBands.find(b => b.condition(rfcn))?.calc(rfcn) || { ulfreq: 0, dlfreq: 0, band: String(rfcn) };
|
||||
|
||||
// CALC BANDS
|
||||
({ frul, offset, ulfreq, dlfreq, band } = bandConfig);
|
||||
|
||||
}
|
||||
|
||||
var carrier = "";
|
||||
var bcc, freq, distance, calte, namebnd;
|
||||
var dist = (json.modem[i].distance)
|
||||
|
||||
var { enbid, cell, pci, lac, cid } = json.modem[i];
|
||||
|
||||
const parts = [lac, cid];
|
||||
var namecid = "LAC/CID";
|
||||
|
||||
if (enbid) {
|
||||
parts.push(enbid);
|
||||
namecid += "/eNB ID";
|
||||
|
||||
if (cell) {
|
||||
parts.push(`/${cell}`);
|
||||
namecid += "/Cell";
|
||||
|
||||
if (pci) {
|
||||
parts.push(`/${pci}`);
|
||||
namecid += "/PCI";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var lactac = parts.join(' / ').replace(' ', ' ').replace('/ /', '/ ').replace('/ /', '/ ')
|
||||
|
||||
var UMTS_MODES = /(HS|3G|UMTS|WCDMA)/i;
|
||||
|
||||
var bcc, scc, cid;
|
||||
var bca = "";
|
||||
var arfcn = json.modem[i].arfcn + " (" + dlfreq + " / " + ulfreq + " MHz)";
|
||||
// name channels and signal/noise
|
||||
if (netmode == "LTE") {
|
||||
var calte = (json.modem[i].lteca)
|
||||
var bwca = json.modem[i].bwca;
|
||||
distance = " ~"+ dist +" km";
|
||||
if (calte > 0) {
|
||||
carrier = "+";
|
||||
scc = json.modem[i].scc;
|
||||
bw = bwca;
|
||||
bca = " / " + bw + " MHz";
|
||||
bcc = " B" + band + "" + scc;
|
||||
} else {
|
||||
scc = "";
|
||||
bcc = " B" + band;
|
||||
if (bw) {
|
||||
bca = " / " + bw + " MHz";
|
||||
} else{
|
||||
bca = ""
|
||||
}
|
||||
}
|
||||
var namech = "EARFCN";
|
||||
var namesnr = "SINR";
|
||||
} else if (UMTS_MODES.test(netmode)) {
|
||||
var namech = "UARFCN";
|
||||
var namesnr = "ECIO";
|
||||
var namecid = "LAC/CID";
|
||||
var lactac = json.modem[i].lac + " / " + json.modem[i].cid;
|
||||
var bcc = " " + band;
|
||||
} else {
|
||||
var namech = "ARFCN";
|
||||
var namesnr = "SINR/ECIO";
|
||||
var namecid = "LAC/CID";
|
||||
var lactac = json.modem[i].lac + " / " + json.modem[i].cid;
|
||||
var bcc = " " + band;
|
||||
}
|
||||
if (bw) {
|
||||
namebnd = _('Network/Band/Bandwidth');
|
||||
} else {
|
||||
namebnd = _('Network/Band');
|
||||
}
|
||||
|
||||
// data by element
|
||||
|
||||
if (document.getElementById('status'+i)) {
|
||||
var view = document.getElementById('status'+i);
|
||||
view.innerHTML = formatModemStatus(json.modem[i], icon, reg);
|
||||
}
|
||||
|
||||
if (document.getElementById('mode'+i)){
|
||||
var view = document.getElementById('mode'+i);
|
||||
if (json.modem[i].signal = 0 || json.modem[i].signal == '') {
|
||||
view.textContent = '--';
|
||||
} else {
|
||||
if (json.modem[i].mode == '') {
|
||||
view.textContent = '--';
|
||||
} else {
|
||||
view.innerHTML = String.format(json.modem[i].mode + "" + carrier + " /"+ bcc +""+ bca);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (document.getElementById('namebnd'+i)){
|
||||
var view = document.getElementById('namebnd'+i);
|
||||
view.innerHTML = String.format(namebnd);
|
||||
}
|
||||
|
||||
if (document.getElementById('chname'+i)){
|
||||
var view = document.getElementById('chname'+i);
|
||||
view.innerHTML = String.format(namech);
|
||||
}
|
||||
|
||||
if (document.getElementById('namecid'+i)){
|
||||
var view = document.getElementById('namecid'+i);
|
||||
view.innerHTML = String.format(namecid);
|
||||
}
|
||||
|
||||
if (document.getElementById('arfcn'+i)){
|
||||
var view = document.getElementById('arfcn'+i);
|
||||
view.innerHTML = String.format(arfcn);
|
||||
}
|
||||
|
||||
if (document.getElementById('lac'+i)){
|
||||
var view = document.getElementById('lac'+i);
|
||||
view.innerHTML = String.format(lactac);
|
||||
}
|
||||
|
||||
if (document.getElementById('snrname'+i)) {
|
||||
var view = document.getElementById('snrname'+i);
|
||||
view.innerHTML = String.format(namesnr);
|
||||
}
|
||||
|
||||
if (document.getElementById('rssi'+i)) {
|
||||
var view = document.getElementById('rssi'+i);
|
||||
if (json.modem[i].rssi == '') {
|
||||
view.textContent = '--';
|
||||
} else {
|
||||
updateProgressBar('rssi', json.modem[i].rssi + ' dBm', -110, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (document.getElementById('sinr'+i)) {
|
||||
var sinrElement = document.getElementById('sinr'+i);
|
||||
var sinrParent = sinrElement ? sinrElement.parentElement : null;
|
||||
|
||||
if (!json.modem[i].sinr || json.modem[i].sinr === "--" || json.modem[i].sinr === "") {
|
||||
if (sinrParent && sinrParent.parentElement) {
|
||||
sinrParent.parentElement.style.display = 'none';
|
||||
}
|
||||
} else {
|
||||
if (sinrParent && sinrParent.parentElement) {
|
||||
sinrParent.parentElement.style.display = '';
|
||||
}
|
||||
if (netmode == "LTE") {
|
||||
updateProgressBar('sinr', json.modem[i].sinr + ' dB', -20, i);
|
||||
} else {
|
||||
updateProgressBar('ecio', json.modem[i].sinr + ' dB', -24, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (document.getElementById('rsrp'+i)) {
|
||||
var rsrpElement = document.getElementById('rsrp'+i);
|
||||
var rsrpParent = rsrpElement ? rsrpElement.parentElement : null;
|
||||
|
||||
if (!json.modem[i].rsrp || json.modem[i].rsrp === "--" || json.modem[i].rsrp === "") {
|
||||
if (rsrpParent && rsrpParent.parentElement) {
|
||||
rsrpParent.parentElement.style.display = 'none';
|
||||
}
|
||||
} else {
|
||||
if (rsrpParent && rsrpParent.parentElement) {
|
||||
rsrpParent.parentElement.style.display = '';
|
||||
}
|
||||
updateProgressBar('rsrp', json.modem[i].rsrp + ' dBm', -140, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (document.getElementById('rsrq'+i)) {
|
||||
var rsrqElement = document.getElementById('rsrq'+i);
|
||||
var rsrqParent = rsrqElement ? rsrqElement.parentElement : null;
|
||||
|
||||
if (!json.modem[i].rsrq || json.modem[i].rsrq === "--" || json.modem[i].rsrq === "") {
|
||||
if (rsrqParent && rsrqParent.parentElement) {
|
||||
rsrqParent.parentElement.style.display = 'none';
|
||||
}
|
||||
} else {
|
||||
if (rsrqParent && rsrqParent.parentElement) {
|
||||
rsrqParent.parentElement.style.display = '';
|
||||
}
|
||||
updateProgressBar('rsrq', json.modem[i].rsrq + ' dB', -20, i);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
}),
|
||||
|
||||
render: function(data){
|
||||
var m, s, o;
|
||||
|
||||
m = new form.Map('modeminfo', _('Modeminfo: Network'), _('Cellular network'));
|
||||
s = m.section(form.TypedSection, 'general', null);
|
||||
var json = JSON.parse(data);
|
||||
|
||||
for (var i = 0; i < json.modem.length; i++) {
|
||||
let status = 'status'+i;
|
||||
let mode = 'mode'+i;
|
||||
let namebnd = 'namebnd'+i;
|
||||
let chname = 'chname'+i;
|
||||
let namecid = 'namecid'+i;
|
||||
let arfcn = 'arfcn'+i;
|
||||
let lac = 'lac'+i;
|
||||
let rssi = 'rssi'+i;
|
||||
let sinr = 'sinr'+i;
|
||||
let snrname = 'snrname'+i;
|
||||
let rsrp = 'rsrp'+i;
|
||||
let rsrq = 'rsrq'+i;
|
||||
let m = i+1;
|
||||
|
||||
if ( json.modem.length > 1 ) {
|
||||
s.tab("modem" + i, _('Modem')+' '+m);
|
||||
o = s.taboption('modem'+i, form.HiddenValue, 'generic');
|
||||
} else {
|
||||
o = s.option(form.HiddenValue, 'generic');
|
||||
}
|
||||
|
||||
o.render = L.bind(function(data){
|
||||
return (
|
||||
E('div', {}, [
|
||||
E('h3', { 'class': 'data-tab' }),
|
||||
E('div', { 'class': 'cbi-section', 'data-title': 'modem'+i }, [
|
||||
E('table', { 'class': 'table' }, [
|
||||
E('tr', { 'class': 'tr cbi-rowstyle-2' }, [
|
||||
E('td', { 'class': 'td left', 'width': '50%' }, [ _('Operator')]),
|
||||
E('td', { 'class': 'td left', 'id': status }, [ '--' ]),
|
||||
]),
|
||||
E('tr', { 'class': 'tr cbi-rowstyle-1' }, [
|
||||
E('td', { 'class': 'td left', 'width': '50%', 'id': namebnd }, [ _('Network/band')]),
|
||||
E('td', { 'class': 'td left', 'id': mode }, [ '--' ]),
|
||||
]),
|
||||
E('tr', { 'class': 'tr cbi-rowstyle-2' }, [
|
||||
E('td', { 'class': 'td left', 'width': '50%', 'id': chname }, [ _('E/U/ARFCN')]),
|
||||
E('td', { 'class': 'td left', 'id': arfcn }, [ '--' ]),
|
||||
]),
|
||||
E('tr', { 'class': 'tr cbi-rowstyle-1' }, [
|
||||
E('td', { 'class': 'td left', 'width': '50%', 'id': namecid }, [ _('LAC/CID')]),
|
||||
E('td', { 'class': 'td left', 'id': lac }, [ '--' ]),
|
||||
]),
|
||||
E('tr', { 'class': 'tr cbi-rowstyle-2' }, [
|
||||
E('td', { 'class': 'td left', 'width': '50%' }, [ _('RSSI')]),
|
||||
E('td', { 'class': 'td left'}, E('div', {'id': rssi, 'class': 'cbi-progressbar', 'title': '--' }, E('div'))),
|
||||
]),
|
||||
E('tr', { 'class': 'tr cbi-rowstyle-1' }, [
|
||||
E('td', { 'class': 'td left', 'width': '50%', 'id': snrname }, [ _('SINR/EcIO')]),
|
||||
E('td', { 'class': 'td left'}, E('div', {'id': sinr, 'class': 'cbi-progressbar', 'title': '--'}, E('div'))),
|
||||
]),
|
||||
E('tr', { 'class': 'tr cbi-rowstyle-2' }, [
|
||||
E('td', { 'class': 'td left', 'width': '50%' }, [ _('RSRP')]),
|
||||
E('td', { 'class': 'td left'}, E('div', {'id': rsrp, 'class': 'cbi-progressbar', 'title': '--'}, E('div'))),
|
||||
]),
|
||||
E('tr', { 'class': 'tr cbi-rowstyle-1' }, [
|
||||
E('td', { 'class': 'td left', 'width': '50%' }, [ _('RSRQ')]),
|
||||
E('td', { 'class': 'td left'}, E('div', {'id': rsrq, 'class': 'cbi-progressbar', 'title': '--'}, E('div'))),
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
)
|
||||
}, this.polldata);
|
||||
o.anonymous = true;
|
||||
o.rmempty = true;
|
||||
};
|
||||
s.anonymous = true;
|
||||
return m.render();
|
||||
|
||||
},
|
||||
handleSaveApply: null,
|
||||
handleSave: null,
|
||||
handleReset: null
|
||||
});
|
||||
@@ -0,0 +1,126 @@
|
||||
'use strict';
|
||||
'require form';
|
||||
'require rpc';
|
||||
'require fs';
|
||||
'require view';
|
||||
'require uci';
|
||||
'require ui';
|
||||
'require tools.widgets as widgets'
|
||||
|
||||
|
||||
/*
|
||||
Written by Konstantine Shevlakov at <shevlakov@132lan.ru> 2023
|
||||
|
||||
Licensed to the GNU General Public License v3.0.
|
||||
|
||||
*/
|
||||
|
||||
var callSerialPort = rpc.declare({
|
||||
object: 'file',
|
||||
method: 'list',
|
||||
params: [ 'path' ],
|
||||
expect: { entries: [] },
|
||||
filter: function(list, params) {
|
||||
var rv = [];
|
||||
for (var i = 0; i < list.length; i++)
|
||||
if (list[i].name.match(/^ttyACM/) ||
|
||||
list[i].name.match(/^ttyUSB/) ||
|
||||
list[i].name.match(/^wwan\d+at\d+/))
|
||||
rv.push(params.path + list[i].name);
|
||||
return rv.sort((a, b) => a.name > b.name);
|
||||
}
|
||||
});
|
||||
|
||||
var callQMIPort = rpc.declare({
|
||||
object: 'file',
|
||||
method: 'list',
|
||||
params: [ 'path' ],
|
||||
expect: { entries: [] },
|
||||
filter: function(list, params) {
|
||||
var rv = [];
|
||||
for (var i = 0; i < list.length; i++)
|
||||
if (list[i].name.match(/^cdc-wdm/))
|
||||
rv.push(params.path + list[i].name);
|
||||
return rv.sort();
|
||||
}
|
||||
});
|
||||
|
||||
var maindesc = _('Modeminfo: Configuration');
|
||||
var mdesc = _('Configuration panel of Modeminfo.');
|
||||
var qfdesc = _('Get modem data via qmicli (experimental). Require install qmi-utils.');
|
||||
var sdesc = _('Select serial port.');
|
||||
var qdesc = _('Select qmi port.');
|
||||
var lacdec = _('Show LAC and CID in decimal.');
|
||||
var mmdesc = _('Get device hardware name via mmcli utility if aviable.');
|
||||
var qmidesc = _('Enable qmi-proxy mode.');
|
||||
var idesc = _('Short info on Overview page');
|
||||
var portplace = _('Please select a port');
|
||||
|
||||
return view.extend({
|
||||
render: function(){
|
||||
var m, s, o;
|
||||
m = new form.Map('modeminfo', maindesc, mdesc);
|
||||
|
||||
s = m.section(form.TypedSection, 'general', _('General option'), null);
|
||||
s.anonymous = true;
|
||||
|
||||
o = s.option(form.Flag, 'index', _('Index page'), idesc);
|
||||
s.anonymous = true;
|
||||
o.rmempty = true;
|
||||
|
||||
o = s.option(form.Flag, 'decimail', _('Show decimal'), lacdec);
|
||||
o.rmempty = true;
|
||||
|
||||
o = s.option(form.ListValue, 'delay', _('Interval'), _('Poll interval data'));
|
||||
o.value('', _('none'));
|
||||
o.value('1', '1 '+_('sec'));
|
||||
o.value('2', '2 '+_('sec'));
|
||||
o.value('5', '5 '+_('sec'));
|
||||
o.value('10', '10 '+_('sec'));
|
||||
o.value('30', '30 '+_('sec'));
|
||||
|
||||
s = m.section(form.TypedSection, 'modeminfo', _('Devices setup'), null);
|
||||
s.anonymous = true;
|
||||
s.addremove = true;
|
||||
|
||||
o = s.option(form.Flag, 'qmi_mode', _('Use QMI'), qfdesc);
|
||||
o.rmempty = true;
|
||||
|
||||
o = s.option(form.ListValue, 'device', _('Data port'), sdesc);
|
||||
o.load = function(section_id) {
|
||||
return callSerialPort('/dev/').then(L.bind(function(devices) {
|
||||
this.keylist = [];
|
||||
this.vallist = [];
|
||||
devices.reverse().forEach(device => this.value(device));
|
||||
return form.Value.prototype.load.apply(this, [section_id]);
|
||||
}, this));
|
||||
};
|
||||
o.placeholder = portplace;
|
||||
o.rmempty = true;
|
||||
o.depends('qmi_mode', '0');
|
||||
|
||||
o = s.option(form.ListValue, 'device_qmi', _('Data port'), qdesc);
|
||||
o.load = function(section_id) {
|
||||
return callQMIPort('/dev/').then(L.bind(function(devices) {
|
||||
this.keylist = [];
|
||||
this.vallist = [];
|
||||
for (var i = 0; i < devices.length; i++)
|
||||
this.value(devices[i]);
|
||||
return form.Value.prototype.load.apply(this, [section_id]);
|
||||
}, this));
|
||||
};
|
||||
o.placeholder = portplace;
|
||||
o.rmempty = true;
|
||||
o.depends('qmi_mode', '1');
|
||||
|
||||
o = s.option(form.Flag, 'mmcli_name', _('Name via mmcli'), mmdesc);
|
||||
o.rmempty = true;
|
||||
o.depends('qmi_mode', '0');
|
||||
|
||||
o = s.option(form.Flag, 'qmi_proxy', _('QMI proxy'), qmidesc);
|
||||
o.rmempty = true;
|
||||
o.depends('qmi_mode', '1');
|
||||
|
||||
return m.render();
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,108 @@
|
||||
'use strict';
|
||||
'require baseclass';
|
||||
'require form';
|
||||
'require fs';
|
||||
'require ui';
|
||||
'require uci';
|
||||
|
||||
/*
|
||||
Written by Konstantine Shevlakov at <shevlakov@132lan.ru> 2023
|
||||
|
||||
Licensed to the GNU General Public License v3.0.
|
||||
|
||||
Special Thanks to Vladislav Kadulin aka @Kodo-kakaku
|
||||
https://github.com/Kodo-kakaku/ to fix update overview page
|
||||
|
||||
*/
|
||||
|
||||
return baseclass.extend({
|
||||
title: _('Cellular network'),
|
||||
|
||||
load: async function() {
|
||||
uci.load('modeminfo');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const timeout = setTimeout(() => {
|
||||
reject(new Error('Timeout: modeminfo execution took too long'));
|
||||
}, 30000); // 30 sec timeout
|
||||
|
||||
fs.exec_direct('/usr/bin/modeminfo')
|
||||
.then(result => {
|
||||
clearTimeout(timeout);
|
||||
resolve(result);
|
||||
})
|
||||
.catch(error => {
|
||||
clearTimeout(timeout);
|
||||
reject(error);
|
||||
});
|
||||
}).catch(error => {
|
||||
console.error('Error loading modeminfo:', error);
|
||||
return '';
|
||||
});
|
||||
},
|
||||
|
||||
render: function(data){
|
||||
if (!data || data.trim() === '') {
|
||||
return E('div', {
|
||||
'class': 'cbi-section',
|
||||
'style': 'color: #999; text-align: center;'
|
||||
}, _('Wait devices information'));
|
||||
}
|
||||
|
||||
try {
|
||||
var json = JSON.parse(data);
|
||||
var index = uci.sections('modeminfo', 'general');
|
||||
let modemTBL = E('div', { 'class': 'cbi-section' });
|
||||
|
||||
if (json.modem && index[0].index == "1"){
|
||||
for (var i = 0; i < json.modem.length; i++) {
|
||||
var signal = document.createElement('div');
|
||||
var icn;
|
||||
var signalIcons = [
|
||||
{ max: -1, icn: 'signal-000-000.svg' },
|
||||
{ max: 0, icn: 'signal-000-000.svg' },
|
||||
{ max: 10, icn: 'signal-000-000.svg' },
|
||||
{ max: 25, icn: 'signal-000-025.svg' },
|
||||
{ max: 50, icn: 'signal-025-050.svg' },
|
||||
{ max: 75, icn: 'signal-050-075.svg' },
|
||||
{ max: Infinity, icn: 'signal-075-100.svg' }
|
||||
];
|
||||
|
||||
var p = json.modem[i].csq_per || 0;
|
||||
var { icn } = signalIcons.find(({ max }) => p <= max);
|
||||
var icon = L.resource(`view/modem/icons/${icn}`);
|
||||
|
||||
var per = p+'%';
|
||||
|
||||
var ca;
|
||||
if (json.modem[i].lteca > 0) {
|
||||
ca = "+";
|
||||
} else {
|
||||
ca = "";
|
||||
}
|
||||
|
||||
signal.innerHTML = String.format(
|
||||
'<span class="ifacebadge">' + json.modem[i].cops + " " +
|
||||
'<img src="%s"/><b>'+per.fontcolor(json.modem[i].csq_col) + "</b> " +
|
||||
json.modem[i].mode+ca + '</span>', icon, p );
|
||||
|
||||
modemTBL.append(
|
||||
E('table', { 'class': 'table' }, [
|
||||
E('tr', { 'class': 'tr' }, [
|
||||
E('td', { 'class': 'td left', 'width': '33%' }, [ json.modem[i].device ]),
|
||||
E('td', { 'class': 'td left', 'id': 'device' }, [ signal ])
|
||||
])
|
||||
])
|
||||
);
|
||||
};
|
||||
return modemTBL;
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error parsing modeminfo data:', error);
|
||||
return E('div', {
|
||||
'class': 'cbi-section',
|
||||
'style': 'color: #999; text-align: center;'
|
||||
}, _('Error loading information'));
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,148 @@
|
||||
"Language: ru\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Last-Translator: Konstantine Shevlyakov <shevlakov@132lan.ru>\n"
|
||||
|
||||
msgid "Modem"
|
||||
msgstr "Модем"
|
||||
|
||||
msgid "Modeminfo"
|
||||
msgstr "Модеминфо"
|
||||
|
||||
msgid "Network"
|
||||
msgstr "Сеть"
|
||||
|
||||
msgid "Hardware"
|
||||
msgstr "Оборудование"
|
||||
|
||||
msgid "Setup"
|
||||
msgstr "Настройка"
|
||||
|
||||
msgid "Modeminfo: Network"
|
||||
msgstr "Модеминфо: Сеть"
|
||||
|
||||
msgid "No Registration"
|
||||
msgstr "Нет регистрации"
|
||||
|
||||
msgid "Registered"
|
||||
msgstr "Зарегистрирован"
|
||||
|
||||
msgid "Searching"
|
||||
msgstr "Поиск сети"
|
||||
|
||||
msgid "Denied"
|
||||
msgstr "Запрет регистрации"
|
||||
|
||||
msgid "Unknown"
|
||||
msgstr "Неизвестно"
|
||||
|
||||
msgid "Roaming"
|
||||
msgstr "Гостевая сеть"
|
||||
|
||||
msgid "No Data"
|
||||
msgstr "Нет данных"
|
||||
|
||||
msgid "Network/Band/Bandwidth"
|
||||
msgstr "Сеть/Диапазон/Полоса"
|
||||
|
||||
msgid "Network/Band"
|
||||
msgstr "Сеть/Диапазон"
|
||||
|
||||
msgid "Cellular network"
|
||||
msgstr "Сотовая сеть"
|
||||
|
||||
msgid "Operator"
|
||||
msgstr "Оператор"
|
||||
|
||||
msgid "Status"
|
||||
msgstr "Состояние"
|
||||
|
||||
msgid "Modeminfo: Hardware"
|
||||
msgstr "Модеминфо: Устройство"
|
||||
|
||||
msgid "Hardware and sim-card info."
|
||||
msgstr "Информация о модеме и сим-карте"
|
||||
|
||||
msgid "Device"
|
||||
msgstr "Устройство"
|
||||
|
||||
msgid "Firmware"
|
||||
msgstr "Встроенное ПО"
|
||||
|
||||
msgid "Chiptemp"
|
||||
msgstr "Температура"
|
||||
|
||||
msgid "In automatic mode detect first answered DATA port."
|
||||
msgstr "В автоматическом режиме находит первый отвечающий порт данных."
|
||||
|
||||
msgid "Please select a port"
|
||||
msgstr "Пожалуйста выберите порт"
|
||||
|
||||
msgid "Modeminfo: Configuration"
|
||||
msgstr "Модеминфо: Конфигурация"
|
||||
|
||||
msgid "Configuration panel of Modeminfo."
|
||||
msgstr "Страница конфигурации Modeminfo."
|
||||
|
||||
msgid "Use QMI"
|
||||
msgstr "Использовать QMI"
|
||||
|
||||
msgid "Get modem data via qmicli (experimental). Require install qmi-utils."
|
||||
msgstr "Получать данные модема через qmicli (экспериментально). Требуется установленный qmi-utils."
|
||||
|
||||
msgid "Data port"
|
||||
msgstr "Порт данных"
|
||||
|
||||
msgid "Select serial port."
|
||||
msgstr "Выберите последовательный порт."
|
||||
|
||||
msgid "Select qmi port."
|
||||
msgstr "Выберите порт qmi."
|
||||
|
||||
msgid "Show decimal"
|
||||
msgstr "Показать в десятичных"
|
||||
|
||||
msgid "Show LAC and CID in decimal."
|
||||
msgstr "Показать LAC и CID соты в десятичных."
|
||||
|
||||
msgid "Get device hardware name via mmcli utility if aviable."
|
||||
msgstr "Если доступно, использовать утилиту mmcli для имени модема."
|
||||
|
||||
msgid "Name via mmcli"
|
||||
msgstr "Имя модема через mmcli"
|
||||
|
||||
msgid "QMI proxy"
|
||||
msgstr "QMI прокси"
|
||||
|
||||
msgid "Enable qmi-proxy mode."
|
||||
msgstr "Задействовать режим прокси."
|
||||
|
||||
msgid "Index page"
|
||||
msgstr "На главную"
|
||||
|
||||
msgid "Short info on Overview page"
|
||||
msgstr "Краткая информация о сети на главной странице"
|
||||
|
||||
msgid "sec"
|
||||
msgstr "сек"
|
||||
|
||||
msgid "none"
|
||||
msgstr "нет"
|
||||
|
||||
msgid "Interval"
|
||||
msgstr "Интервал"
|
||||
|
||||
msgid "Poll interval data"
|
||||
msgstr "Интервал обновления данных"
|
||||
|
||||
msgid "General option"
|
||||
msgstr "Общие настройки"
|
||||
|
||||
msgid "Devices setup"
|
||||
msgstr "Настройки устройств"
|
||||
|
||||
msgid "Wait devices information"
|
||||
msgstr "Ожидание ответа от устройств"
|
||||
|
||||
msgid "Error loading information"
|
||||
msgstr "Получение данных завершилось ошибкой"
|
||||
@@ -0,0 +1 @@
|
||||
zh_Hans
|
||||
@@ -0,0 +1,132 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||
|
||||
msgid "Modem"
|
||||
msgstr "移动网络"
|
||||
|
||||
msgid "Modeminfo"
|
||||
msgstr "调制解调器信息"
|
||||
|
||||
msgid "Network"
|
||||
msgstr "网络"
|
||||
|
||||
msgid "China Mobile"
|
||||
msgstr "中国移动"
|
||||
|
||||
msgid "China Unicom"
|
||||
msgstr "中国联通"
|
||||
|
||||
msgid "China Telecom"
|
||||
msgstr "中国电信"
|
||||
|
||||
msgid "Hardware"
|
||||
msgstr "硬件"
|
||||
|
||||
msgid "Setup"
|
||||
msgstr "设置"
|
||||
|
||||
msgid "Modeminfo: Network"
|
||||
msgstr "调制解调器信息: 网络"
|
||||
|
||||
msgid "No Registration"
|
||||
msgstr "未注册"
|
||||
|
||||
msgid "Registered"
|
||||
msgstr "已注册"
|
||||
|
||||
msgid "Searching"
|
||||
msgstr "搜索中"
|
||||
|
||||
msgid "Denied"
|
||||
msgstr "禁止注册"
|
||||
|
||||
msgid "Unknown"
|
||||
msgstr "未知"
|
||||
|
||||
msgid "Roaming"
|
||||
msgstr "漫游"
|
||||
|
||||
msgid "No Data"
|
||||
msgstr "无数据"
|
||||
|
||||
msgid "Network/Band/Bandwidth"
|
||||
msgstr "网络/频段/带宽"
|
||||
|
||||
msgid "Network/Band"
|
||||
msgstr "网络/频段"
|
||||
|
||||
msgid "Cellular network"
|
||||
msgstr "蜂窝网络"
|
||||
|
||||
msgid "Operator"
|
||||
msgstr "运营商"
|
||||
|
||||
msgid "Status"
|
||||
msgstr "状态"
|
||||
|
||||
|
||||
msgid "Modeminfo: Hardware"
|
||||
msgstr "调制解调器信息: 硬件"
|
||||
|
||||
msgid "Hardware and sim card info."
|
||||
msgstr "硬件和sim卡信息。"
|
||||
|
||||
msgid "Device"
|
||||
msgstr "设备"
|
||||
|
||||
msgid "Firmware"
|
||||
msgstr "固件"
|
||||
|
||||
msgid "Chiptemp"
|
||||
msgstr "芯片温度"
|
||||
|
||||
msgid "In automatic mode detect first answered DATA port."
|
||||
msgstr "在自动模式下,检测第一个应答的DATA端口。"
|
||||
|
||||
msgid "Please select a port"
|
||||
msgstr "请选择端口"
|
||||
|
||||
msgid "Modeminfo: Configuration"
|
||||
msgstr "调制解调器信息:配置"
|
||||
|
||||
msgid "Configuration panel of Modeminfo."
|
||||
msgstr "调制解调器信息配置面板。"
|
||||
|
||||
msgid "Use QMI"
|
||||
msgstr "使用 QMI"
|
||||
|
||||
msgid "Get modem data via qmicli (experimental). Require install qmi-utils."
|
||||
msgstr "通过qmicli获取调制解调器数据(实验)。需要安装qmi utils。"
|
||||
|
||||
msgid "Data port"
|
||||
msgstr "数据端口"
|
||||
|
||||
msgid "Select serial port."
|
||||
msgstr "选择串口。"
|
||||
|
||||
msgid "Select qmi port."
|
||||
msgstr "选择qmi端口。"
|
||||
|
||||
msgid "Show decimal"
|
||||
msgstr "十进制显示"
|
||||
|
||||
msgid "Show LAC and CID in decimal."
|
||||
msgstr "以十进制显示LAC和CID。"
|
||||
|
||||
msgid "Get device hardware name via mmcli utility if aviable."
|
||||
msgstr "如果可用,请通过mmcli 获取设备硬件名称。"
|
||||
|
||||
msgid "Name via mmcli"
|
||||
msgstr "通过mmcli命名"
|
||||
|
||||
msgid "QMI proxy"
|
||||
msgstr "QMI 代理"
|
||||
|
||||
msgid "Enable qmi-proxy mode."
|
||||
msgstr "启用qmi代理模式。"
|
||||
|
||||
msgid "Index page"
|
||||
msgstr "主页显示"
|
||||
|
||||
msgid "Short info on Overview page"
|
||||
msgstr "在概览页面显示简单的信息。"
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"admin/modem": {
|
||||
"title": "Modem",
|
||||
"order": 45,
|
||||
"action": {
|
||||
"type": "firstchild",
|
||||
"recurse": true
|
||||
}
|
||||
},
|
||||
|
||||
"admin/modem/main": {
|
||||
"title": "Modeminfo",
|
||||
"order": 10,
|
||||
"action": {
|
||||
"type": "alias",
|
||||
"path": "admin/modem/main/main"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-app-modeminfo" ],
|
||||
"uci": { "modeminfo": true }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/modem/main/main": {
|
||||
"title": "Network",
|
||||
"order": 51,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "modem/main"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/modem/main/hw": {
|
||||
"title": "Hardware",
|
||||
"order": 52,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "modem/hw"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/modem/main/config": {
|
||||
"title": "Setup",
|
||||
"order": 53,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "modem/setup"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"luci-app-modeminfo": {
|
||||
"description": "Grant access to modeminfo configuration",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"file": [ "read" ],
|
||||
"luci": [ "getConntrackHelpers" ]
|
||||
},
|
||||
"file": {
|
||||
"/usr/bin/modeminfo": [ "exec" ],
|
||||
"/usr/share/modeminfo/scripts/rmtmp": [ "exec" ]
|
||||
},
|
||||
"uci": [ "modeminfo" ]
|
||||
},
|
||||
"write": {
|
||||
"ubus": {
|
||||
"file": [ "write" ]
|
||||
},
|
||||
|
||||
"uci": [ "modeminfo" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 60 KiB |