v1.2. UI detector refactoring

This commit is contained in:
gSpot
2024-01-20 19:08:49 +03:00
parent be0912d7ae
commit 9364dabe0a
18 changed files with 601 additions and 640 deletions

View File

@@ -19,15 +19,15 @@ Internet-detector is an application for checking the availability of the Interne
**OpenWrt >= 21.02:**
opkg update
wget --no-check-certificate -O /tmp/internet-detector_1.1-0_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector_1.1-0_all.ipk
opkg install /tmp/internet-detector_1.1-0_all.ipk
rm /tmp/internet-detector_1.1-0_all.ipk
wget --no-check-certificate -O /tmp/internet-detector_1.2-0_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector_1.2-0_all.ipk
opkg install /tmp/internet-detector_1.2-0_all.ipk
rm /tmp/internet-detector_1.2-0_all.ipk
/etc/init.d/internet-detector start
/etc/init.d/internet-detector enable
wget --no-check-certificate -O /tmp/luci-app-internet-detector_1.1-0_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-app-internet-detector_1.1-0_all.ipk
opkg install /tmp/luci-app-internet-detector_1.1-0_all.ipk
rm /tmp/luci-app-internet-detector_1.1-0_all.ipk
wget --no-check-certificate -O /tmp/luci-app-internet-detector_1.2-0_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-app-internet-detector_1.2-0_all.ipk
opkg install /tmp/luci-app-internet-detector_1.2-0_all.ipk
rm /tmp/luci-app-internet-detector_1.2-0_all.ipk
/etc/init.d/rpcd restart
Email notification:
@@ -36,9 +36,9 @@ Email notification:
i18n-ru:
wget --no-check-certificate -O /tmp/luci-i18n-internet-detector-ru_1.1-0_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-i18n-internet-detector-ru_1.1-0_all.ipk
opkg install /tmp/luci-i18n-internet-detector-ru_1.1-0_all.ipk
rm /tmp/luci-i18n-internet-detector-ru_1.1-0_all.ipk
wget --no-check-certificate -O /tmp/luci-i18n-internet-detector-ru_1.2-0_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-i18n-internet-detector-ru_1.2-0_all.ipk
opkg install /tmp/luci-i18n-internet-detector-ru_1.2-0_all.ipk
rm /tmp/luci-i18n-internet-detector-ru_1.2-0_all.ipk
**[OpenWrt 19.07](https://github.com/gSpotx2f/luci-app-internet-detector/tree/19.07)**
@@ -47,4 +47,3 @@ i18n-ru:
![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/01.jpg)
![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/02.jpg)
![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/03.jpg)
![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/04.jpg)

View File

@@ -1,11 +1,11 @@
#
# (с) 2023 gSpot (https://github.com/gSpotx2f/luci-app-internet-detector)
# (с) 2024 gSpot (https://github.com/gSpotx2f/luci-app-internet-detector)
#
include $(TOPDIR)/rules.mk
PKG_NAME:=internet-detector
PKG_VERSION:=1.1
PKG_VERSION:=1.2
PKG_RELEASE:=0
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>

View File

@@ -2,16 +2,6 @@ config main 'config'
option mode '1'
option enable_logger '1'
config ui 'ui'
list hosts '8.8.8.8'
list hosts '1.1.1.1'
option check_type '0'
option tcp_port '53'
option interval_up '6'
option interval_down '1'
option connection_attempts '1'
option connection_timeout '1'
config instance 'internet'
option enabled '1'
list hosts '8.8.8.8'

View File

@@ -3,9 +3,9 @@
START=97
STOP=01
PROG=/usr/bin/internet-detector
PROG="/usr/bin/internet-detector"
config_app() {
run_instance() {
config_get enabled "$1" enabled "0"
if [ $enabled = "1" ]; then
$PROG service "$1"
@@ -16,7 +16,7 @@ start() {
config_load internet-detector
config_get mode "config" mode "0"
if [ $mode = "1" ]; then
config_foreach config_app "instance"
config_foreach run_instance "instance"
fi
}

View File

@@ -8,7 +8,7 @@
luaposix
libuci-lua
(с) 2023 gSpot (https://github.com/gSpotx2f/luci-app-internet-detector)
(с) 2024 gSpot (https://github.com/gSpotx2f/luci-app-internet-detector)
--]]
-- Importing packages
@@ -26,13 +26,16 @@ local uci = require("uci")
-- Default settings
local InternetDetector = {
mode = 0,
mode = 0, -- 0: disabled, 1: Service, 2: UI detector
enableLogger = true,
hostname = "OpenWrt",
appName = "internet-detector",
commonDir = "/tmp/run",
pingCmd = "/bin/ping",
pingParams = "-c 1",
uiRunTime = 30,
noModules = false,
uiAvailModules = { mod_public_ip = true },
debug = false,
serviceConfig = {
hosts = {
@@ -51,11 +54,13 @@ local InternetDetector = {
},
modules = {},
parsedHosts = {},
uiCounter = 0,
}
InternetDetector.configDir = string.format("/etc/%s", InternetDetector.appName)
InternetDetector.modulesDir = string.format("/usr/lib/%s", InternetDetector.appName)
-- Loading settings from UCI
local uciCursor = uci.cursor()
InternetDetector.mode = tonumber(
uciCursor:get(InternetDetector.appName, "config", "mode"))
@@ -162,6 +167,8 @@ function InternetDetector:loadModules()
for item in modulesDir do
if item:match("^mod_") then
local modName = item:gsub("%.lua$", "")
if self.noModules and not self.uiAvailModules[modName] then
else
local modConfig = {}
for k, v in pairs(self.serviceConfig) do
if k:match("^" .. modName) then
@@ -181,6 +188,7 @@ function InternetDetector:loadModules()
end
end
end
end
table.sort(self.modules, function(a, b) return a.runPrio < b.runPrio end)
end
end
@@ -213,7 +221,6 @@ function InternetDetector:pingHost(host)
)
local retCode = os.execute(ping)
-- Debug
if self.debug then
io.stdout:write(string.format(
"--- Ping ---\ntime = %s\n%s\nretCode = %s\n", os.time(), ping, retCode)
@@ -329,12 +336,17 @@ function InternetDetector:breakMain(signo)
RUNNING = false
end
function InternetDetector:resetUiCounter(signo)
self.uiCounter = 0
end
function InternetDetector:main()
signal.signal(signal.SIGTERM, function(signo) self:breakMain(signo) end)
signal.signal(signal.SIGINT, function(signo) self:breakMain(signo) end)
signal.signal(signal.SIGQUIT, function(signo) self:breakMain(signo) end)
signal.signal(signal.SIGUSR1, function(signo) self:resetUiCounter(signo) end)
local lastStatus, currentStatus, timeNow, timeDiff, lastTime
local lastStatus, currentStatus, mTimeNow, mTimeDiff, mLastTime, uiTimeNow, uiLastTime
local interval = self.serviceConfig.interval_up
local counter = 0
local onStart = true
@@ -367,16 +379,16 @@ function InternetDetector:main()
counter = 0
end
timeDiff = 0
mTimeDiff = 0
for _, e in ipairs(self.modules) do
timeNow = time.clock_gettime(time.CLOCK_MONOTONIC).tv_sec
if lastTime then
timeDiff = timeDiff + timeNow - lastTime
mTimeNow = time.clock_gettime(time.CLOCK_MONOTONIC).tv_sec
if mLastTime then
mTimeDiff = mTimeDiff + mTimeNow - mLastTime
else
timeDiff = 1
mTimeDiff = 1
end
lastTime = timeNow
e:run(currentStatus, lastStatus, timeDiff)
mLastTime = mTimeNow
e:run(currentStatus, lastStatus, mTimeDiff)
end
local modulesStatus = {}
@@ -393,6 +405,19 @@ function InternetDetector:main()
lastStatus = currentStatus
unistd.sleep(1)
counter = counter + 1
if self.mode == 2 then
uiTimeNow = time.clock_gettime(time.CLOCK_MONOTONIC).tv_sec
if uiLastTime then
self.uiCounter = self.uiCounter + uiTimeNow - uiLastTime
else
self.uiCounter = self.uiCounter + 1
end
uiLastTime = uiTimeNow
if self.uiCounter >= self.uiRunTime then
self:breakMain(signal.SIGTERM)
end
end
end
end
@@ -490,13 +515,27 @@ function InternetDetector:stop()
break
end
end
end
function InternetDetector:setSIGUSR()
local appName = self.appName:gsub("-", "%%-")
local ok, commonDir = pcall(dirent.files, self.commonDir)
if ok then
for item in commonDir do
if item:match("^" .. appName .. ".-%.pid$") then
pidValue = self:readValueFromFile(string.format("%s/%s", self.commonDir, item))
if pidValue then
signal.kill(tonumber(pidValue), signal.SIGUSR1)
end
end
end
end
end
function InternetDetector:preRun()
-- Exit if internet-detector mode != 1(Service)
if self.mode ~= 1 then
io.stderr:write(string.format('Start failed, mode != 1\n', self.appName))
-- Exit if internet-detector mode != (1 or 2)
if self.mode ~= 1 and self.mode ~= 2 then
io.stderr:write(string.format('Start failed, mode != (1 or 2)\n', self.appName))
os.exit(0)
end
if stat.stat(self.pidFile) then
@@ -528,7 +567,6 @@ function InternetDetector:run()
)
end
-- Debug
if self.debug then
local function inspectTable()
local tables = {}, f
@@ -597,6 +635,10 @@ end
function InternetDetector:setServiceConfig(instance)
if self:loadUCIConfig("instance", instance) then
self:parseHosts()
if self.mode == 2 then
self.enableLogger = false
self.noModules = true
end
return true
end
end
@@ -605,12 +647,12 @@ end
local function help()
return string.format(
"Usage: %s service <UCI instance> | nodaemon <UCI instance> | debug <UCI instance> | stop | status | inet-status | poll [<attempts num>] [<timeout sec>] | --help",
"Usage: %s service <UCI instance> | nodaemon <UCI instance> | debug <UCI instance> | stop | status | inet-status | uipoll | --help",
arg[0]
)
end
local helpArgs = { ["-h"] = true, ["--help"] = true, ["help"] = true }
local helpArgs = { ["-h"] = true, ["--help"] = true, help = true }
if arg[1] == "service" then
if arg[2] then
if InternetDetector:setServiceConfig(arg[2]) then
@@ -651,20 +693,12 @@ elseif arg[1] == "status" then
print(InternetDetector:status())
elseif arg[1] == "inet-status" then
print(InternetDetector:inetStatus())
elseif arg[1] == "poll" then
if InternetDetector:loadUCIConfig("ui", "ui") then
InternetDetector:parseHosts()
if arg[2] and arg[2]:match("[0-9]+") then
InternetDetector.serviceConfig.connection_attempts = tonumber(arg[2])
if arg[3] and arg[3]:match("[0-9]+") then
InternetDetector.serviceConfig.connection_timeout = tonumber(arg[3])
end
end
print(InternetDetector:poll())
else
elseif arg[1] == "uipoll" then
if InternetDetector:status() == "stoped" then
os.exit(126)
else
InternetDetector:setSIGUSR()
print(InternetDetector:inetStatus())
end
elseif helpArgs[arg[1]] then
print(help())

View File

@@ -12,8 +12,8 @@ local Module = {
runInterval = 5,
sysLedsDir = "/sys/class/leds",
ledName = nil,
ledAction1 = 2,
ledAction2 = 1,
ledAction1 = 2, -- 1: off, 2: on, 3: blink
ledAction2 = 1, -- 1: off, 2: on, 3: blink
status = nil,
_enabled = false,
_ledDir = nil,

View File

@@ -7,6 +7,7 @@ local Module = {
name = "mod_public_ip",
runPrio = 50,
config = {
noModules = false,
debug = false,
serviceConfig = {
iface = nil,
@@ -65,7 +66,7 @@ local Module = {
}
function Module:runIpScript()
if self.enableIpScript and unistd.access(self.ipScript, "r") then
if not self.config.noModules and self.enableIpScript and unistd.access(self.ipScript, "r") then
stdlib.setenv("PUBLIC_IP", self.status)
os.execute(string.format('/bin/sh "%s" &', self.ipScript))
end

View File

@@ -1,10 +1,10 @@
#
# (с) 2023 gSpot (https://github.com/gSpotx2f/luci-app-internet-detector)
# (с) 2024 gSpot (https://github.com/gSpotx2f/luci-app-internet-detector)
#
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.1-0
PKG_VERSION:=1.2-0
LUCI_TITLE:=LuCI support for internet-detector
LUCI_DEPENDS:=+internet-detector
LUCI_PKGARCH:=all

View File

@@ -64,7 +64,7 @@ const btnStyleDisabled = 'btn cbi-button-reset';
const btnStyleApply = 'btn cbi-button-apply';
var Timefield = ui.Textfield.extend({
secToString: function(value) {
secToString(value) {
let string = '0';
if(/^\d+$/.test(value)) {
value = Number(value);
@@ -81,7 +81,7 @@ var Timefield = ui.Textfield.extend({
return string;
},
render: function() {
render() {
let frameEl = E('div', { 'id': this.options.id }),
inputEl = E('input', {
'id' : this.options.id ? 'widget.' + this.options.id : null,
@@ -98,7 +98,7 @@ var Timefield = ui.Textfield.extend({
return this.bind(frameEl);
},
getValue: function() {
getValue() {
let rawValue = this.node.querySelector('input').value,
value = 0,
res = rawValue.match(/^(\d+)([hms]?)$/);
@@ -121,7 +121,7 @@ var Timefield = ui.Textfield.extend({
return String(value);
},
setValue: function(value) {
setValue(value) {
let inputEl = this.node.querySelector('input');
inputEl.value = this.secToString(value);
},
@@ -140,10 +140,6 @@ return view.extend({
inetStatusArea : E('div', { 'class': 'cbi-value-field', 'id': 'inetStatusArea' }),
serviceStatusLabel : E('em', { 'id': 'serviceStatusLabel' }),
initButton : null,
uiPollCounter : 0,
uiPollState : null,
uiCheckIntervalUp : null,
uiCheckIntervalDown : null,
currentAppMode : '0',
defaultHosts : [ '8.8.8.8', '1.1.1.1' ],
leds : [],
@@ -164,7 +160,7 @@ return view.extend({
expect: { result: false }
}),
getInitStatus: function() {
getInitStatus() {
return this.callInitStatus(this.appName).then(res => {
if(res) {
return res[this.appName].enabled;
@@ -177,7 +173,7 @@ return view.extend({
});
},
handleServiceAction: function(action) {
handleServiceAction(action) {
return this.callInitAction(this.appName, action).then(success => {
if(!success) {
throw _('Command failed');
@@ -189,12 +185,24 @@ return view.extend({
});
},
setInternetStatus: function() {
callUIPoll: rpc.declare({
object: 'luci.internet-detector',
method: 'UIPoll',
expect: { '': {} }
}),
getUIPoll() {
return this.callUIPoll().then(data => {
return data;
});
},
setInternetStatus() {
this.inetStatusArea.innerHTML = '';
if(!this.inetStatus || !this.inetStatus.instances || this.inetStatus.instances.length === 0) {
let label = E('span', { 'class': 'id-label-status id-undefined' }, _('Undefined'))
if(this.currentAppMode !== '0' && this.appStatus !== 'stoped') {
let label = E('span', { 'class': 'id-label-status id-undefined' }, _('Undefined'));
if((this.currentAppMode === '1' && this.appStatus !== 'stoped') || this.currentAppMode === '2') {
label.classList.add('spinning');
};
this.inetStatusArea.append(label);
@@ -219,8 +227,7 @@ return view.extend({
this.inetStatusArea.append(
E('span', { 'class': className }, '%s%s%s'.format(
(this.currentAppMode === '1') ? i.instance + ': ' : '',
status, publicIp)
i.instance + ': ', status, publicIp)
)
);
};
@@ -233,7 +240,7 @@ return view.extend({
};
},
inetStatusFromJson: function(res) {
inetStatusFromJson(res) {
let inetStatData = null;
if(res.code === 0) {
try {
@@ -243,7 +250,7 @@ return view.extend({
return inetStatData;
},
servicePoll: function() {
servicePoll() {
return Promise.all([
fs.exec(this.execPath, [ 'status' ]),
fs.exec(this.execPath, [ 'inet-status' ]),
@@ -259,31 +266,18 @@ return view.extend({
});
},
uiPoll: function() {
this.uiPollCounter = ++this.uiPollCounter;
if((this.uiPollState === 0 && this.uiPollCounter % this.uiCheckIntervalUp) ||
(this.uiPollState === 1 && this.uiPollCounter % this.uiCheckIntervalDown)) {
return;
};
this.uiPollCounter = 0;
return fs.exec(this.execPath, [ 'poll' ]).then(res => {
let inetStatData = this.inetStatusFromJson(res);
if(inetStatData.instances[0]) {
this.uiPollState = inetStatData.instances[0].inet;
};
this.inetStatus = inetStatData;
uiPoll() {
return this.getUIPoll().then(status => {
this.inetStatus = status;
this.setInternetStatus();
});
},
serviceRestart: function() {
serviceRestart() {
return this.handleServiceAction('restart');
},
serviceRestartHandler: function() {
serviceRestartHandler() {
poll.stop();
return this.serviceRestart().then(() => {
window.setTimeout(() => this.servicePoll(), 1000);
@@ -294,7 +288,7 @@ return view.extend({
CBITimeInput: form.Value.extend({
__name__ : 'CBI.TimeInput',
renderWidget: function(section_id, option_index, cfgvalue) {
renderWidget(section_id, option_index, cfgvalue) {
let value = (cfgvalue != null) ? cfgvalue : this.default,
widget = new Timefield(value, {
id : this.cbid(section_id),
@@ -318,7 +312,7 @@ return view.extend({
CBIBlockInetStatus: form.Value.extend({
__name__ : 'CBI.BlockInetStatus',
__init__ : function(map, section, ctx) {
__init__(map, section, ctx) {
this.map = map;
this.section = section;
this.ctx = ctx;
@@ -326,7 +320,7 @@ return view.extend({
this.rmempty = true;
},
renderWidget: function(section_id, option_index, cfgvalue) {
renderWidget(section_id, option_index, cfgvalue) {
this.ctx.setInternetStatus();
return E([
@@ -340,7 +334,7 @@ return view.extend({
CBIBlockServiceStatus: form.Value.extend({
__name__ : 'CBI.BlockServiceStatus',
__init__ : function(map, section, ctx) {
__init__(map, section, ctx) {
this.map = map;
this.section = section;
this.ctx = ctx;
@@ -348,7 +342,7 @@ return view.extend({
this.rmempty = true;
},
renderWidget: function(section_id, option_index, cfgvalue) {
renderWidget(section_id, option_index, cfgvalue) {
return E([
E('label', { 'class': 'cbi-value-title', 'for': 'serviceStatusLabel' },
_('Service')
@@ -363,7 +357,7 @@ return view.extend({
CBIBlockInitButton: form.Value.extend({
__name__ : 'CBI.BlockInitButton',
__init__ : function(map, section, ctx) {
__init__(map, section, ctx) {
this.map = map;
this.section = section;
this.ctx = ctx;
@@ -371,7 +365,7 @@ return view.extend({
this.rmempty = true;
},
renderWidget: function(section_id, option_index, cfgvalue) {
renderWidget(section_id, option_index, cfgvalue) {
this.ctx.initButton = E('button', {
'class': (!this.ctx.initStatus) ? btnStyleDisabled : btnStyleEnabled,
'click': ui.createHandlerFn(this, () => {
@@ -413,7 +407,7 @@ return view.extend({
CBIBlockFileEdit: form.Value.extend({
__name__ : 'CBI.BlockFileEdit',
__init__ : function(map, section, ctx, id, file, title, description, callback) {
__init__(map, section, ctx, id, file, title, description, callback) {
this.map = map;
this.section = section;
this.ctx = ctx;
@@ -427,11 +421,11 @@ return view.extend({
this.content = '';
},
cfgvalue: function(section_id, option) {
cfgvalue(section_id, option) {
return this.content;
},
formvalue: function(section_id) {
formvalue(section_id) {
let value = this.content;
let textarea = document.getElementById('widget.file_edit.content.' + this.id);
if(textarea) {
@@ -440,7 +434,7 @@ return view.extend({
return value;
},
write: function(section_id, formvalue) {
write(section_id, formvalue) {
return fs.write(this.file, formvalue).then(rc => {
ui.addNotification(null, E('p', _('Contents have been saved.')),
'info');
@@ -453,13 +447,13 @@ return view.extend({
});
},
load: function() {
load() {
return L.resolveDefault(fs.read(this.file), '').then(c => {
this.content = c;
});
},
renderWidget: function(section_id, option_index, cfgvalue) {
renderWidget(section_id, option_index, cfgvalue) {
return E('textarea', {
'id' : 'widget.file_edit.content.' + this.id,
'class' : 'cbi-input-textarea',
@@ -471,7 +465,7 @@ return view.extend({
},
}),
load: function() {
load() {
return Promise.all([
fs.exec(this.execPath, [ 'status' ]),
this.getInitStatus(),
@@ -484,7 +478,7 @@ return view.extend({
});
},
render: function(data) {
render(data) {
if(!data) {
return;
};
@@ -498,8 +492,6 @@ return view.extend({
this.mta = true;
};
this.currentAppMode = uci.get(this.appName, 'config', 'mode');
this.uiCheckIntervalUp = Number(uci.get(this.appName, 'ui', 'interval_up'));
this.uiCheckIntervalDown = Number(uci.get(this.appName, 'ui', 'interval_down'));
let s, o, ss;
let m = new form.Map(this.appName,
@@ -549,32 +541,27 @@ return view.extend({
);
s = m.section(form.NamedSection, 'config', 'main');
/* Service instances configuration */
s.tab('service', _('Service configuration'));
if(this.currentAppMode !== '2') {
// enable_logger
o = s.taboption('service', form.Flag, 'enable_logger',
o = s.option(form.Flag, 'enable_logger',
_('Enable logging'),
_('Write messages to the system log.')
);
o.rmempty = false;
};
o = s.taboption('service', form.SectionValue, 'instance', form.GridSection,
'instance'
);
ss = o.subsection;
s = m.section(form.GridSection, 'instance');
ss.title = _('Service instances');
ss.addremove = true;
ss.sortable = true;
ss.nodescriptions = true;
ss.addbtntitle = _('Add instance');
s.title = _('Service instances');
s.addremove = true;
s.sortable = true;
s.nodescriptions = true;
s.addbtntitle = _('Add instance');
ss.tab('main', _('Main settings'));
s.tab('main', _('Main settings'));
function makeIntervalOptions(list) {
list.value(2, '2 ' + _('sec'));
@@ -591,7 +578,7 @@ return view.extend({
}
// enabled
o = ss.taboption('main', form.Flag, 'enabled',
o = s.taboption('main', form.Flag, 'enabled',
_('Enabled'),
);
o.rmempty = false;
@@ -600,16 +587,17 @@ return view.extend({
o.modalonly = false;
// hosts
o = ss.taboption('main', form.DynamicList,
o = s.taboption('main', form.DynamicList,
'hosts', _('Hosts'),
_('Hosts to check Internet availability. Hosts are polled (in list order) until at least one of them responds.')
);
//o.datatype = 'or(host,hostport)';
o.datatype = 'or(or(host,hostport),ipaddrport(1))';
o.default = this.defaultHosts;
o.rmempty = false;
// check_type
o = ss.taboption('main', form.ListValue,
o = s.taboption('main', form.ListValue,
'check_type', _('Check type'),
_('Host availability check type.')
);
@@ -619,7 +607,7 @@ return view.extend({
o.modalonly = true;
// tcp_port
o = ss.taboption('main', form.Value,
o = s.taboption('main', form.Value,
'tcp_port', _('TCP port'),
_('Default port value for TCP connections.')
);
@@ -629,7 +617,7 @@ return view.extend({
o.modalonly = true;
// icmp_packet_size
o = ss.taboption('main', form.ListValue,
o = s.taboption('main', form.ListValue,
'icmp_packet_size', _('ICMP packet data size'));
o.value(1, _('Small: 1 byte'));
o.value(32, _('Windows: 32 bytes'));
@@ -642,14 +630,14 @@ return view.extend({
o.modalonly = true;
// iface
o = ss.taboption('main', widgets.DeviceSelect,
o = s.taboption('main', widgets.DeviceSelect,
'iface', _('Interface'),
_('Network interface for Internet access. If not specified, the default interface is used.')
);
o.noaliases = true;
// interval_up
o = ss.taboption('main', form.ListValue,
o = s.taboption('main', form.ListValue,
'interval_up', _('Alive interval'),
_('Hosts polling interval when the Internet is up.')
);
@@ -658,7 +646,7 @@ return view.extend({
makeIntervalOptions(o);
// interval_down
o = ss.taboption('main', form.ListValue,
o = s.taboption('main', form.ListValue,
'interval_down', _('Dead interval'),
_('Hosts polling interval when the Internet is down.')
);
@@ -667,7 +655,7 @@ return view.extend({
makeIntervalOptions(o);
// connection_attempts
o = ss.taboption('main', form.ListValue,
o = s.taboption('main', form.ListValue,
'connection_attempts', _('Connection attempts'),
_('Maximum number of attempts to connect to each host.')
);
@@ -680,7 +668,7 @@ return view.extend({
o.default = '2';
// connection_timeout
o = ss.taboption('main', form.ListValue,
o = s.taboption('main', form.ListValue,
'connection_timeout', _('Connection timeout'),
_('Maximum timeout for waiting for a response from the host.')
);
@@ -700,15 +688,23 @@ return view.extend({
/* Modules */
ss.tab('led_control', _('LED control'));
ss.tab('reboot_device', _('Reboot device'));
ss.tab('restart_network', _('Restart network'));
ss.tab('restart_modem', _('Restart modem'));
ss.tab('public_ip', _('Public IP address'));
ss.tab('email', _('Email notification'));
ss.tab('user_scripts', _('User scripts'));
if(this.currentAppMode !== '2') {
s.tab('led_control', _('LED control'));
s.tab('reboot_device', _('Reboot device'));
s.tab('restart_network', _('Restart network'));
s.tab('restart_modem', _('Restart modem'));
};
ss.addModalOptions = (s, section_id, ev) => {
s.tab('public_ip', _('Public IP address'));
if(this.currentAppMode !== '2') {
s.tab('email', _('Email notification'));
s.tab('user_scripts', _('User scripts'));
};
s.addModalOptions = (s, section_id, ev) => {
if(this.currentAppMode !== '2') {
// LED control
@@ -740,7 +736,6 @@ return view.extend({
_('Action when connected'));
o.depends({ mod_led_control_enabled: '1' });
o.modalonly = true;
//o.value(0, _('Nothing'));
o.value(1, _('Off'));
o.value(2, _('On'));
o.value(3, _('Blink'));
@@ -919,6 +914,8 @@ return view.extend({
o.modalonly = true;
};
};
// Public IP address
o = s.taboption('public_ip', form.DummyValue, '_dummy');
@@ -982,6 +979,8 @@ return view.extend({
o.value(i, i + ' ' + _('sec'));
};
if(this.currentAppMode !== '2') {
// enable_ip_script
o = s.taboption('public_ip', form.Flag, 'mod_public_ip_enable_ip_script',
_('Enable public-ip-script'));
@@ -997,6 +996,7 @@ return view.extend({
);
o.modalonly = true;
// Email notification
o = s.taboption('email', form.DummyValue, '_dummy');
@@ -1141,107 +1141,7 @@ return view.extend({
o.modalonly = true;
};
/* UI detector configuration */
s.tab('ui_detector', _('UI detector configuration'));
o = s.taboption('ui_detector', form.SectionValue,
'ui', form.NamedSection, 'ui'
);
ss = o.subsection;
let makeUIIntervalOptions = L.bind(function(list) {
list.value(1, '%d %s'.format(this.pollInterval, _('sec')));
list.value(2, '%d %s'.format(this.pollInterval * 2, _('sec')));
list.value(3, '%d %s'.format(this.pollInterval * 3, _('sec')));
list.value(4, '%d %s'.format(this.pollInterval * 4, _('sec')));
list.value(5, '%d %s'.format(this.pollInterval * 5, _('sec')));
list.value(6, '%d %s'.format(this.pollInterval * 6, _('sec')));
}, this);
// hosts
o = ss.option(form.DynamicList,
'hosts', _('Hosts'),
_('Hosts to check Internet availability. Hosts are polled (in list order) until at least one of them responds.')
);
o.datatype = 'or(or(host,hostport),ipaddrport(1))';
o.default = this.defaultHosts;
o.rmempty = false;
// check_type
o = ss.option(form.ListValue,
'check_type', _('Check type'),
_('Host availability check type.')
);
o.value(0, _('TCP port connection'));
o.value(1, _('ICMP-echo request (ping)'));
o.default = '0';
// tcp_port
o = ss.option(form.Value,
'tcp_port', _('TCP port'),
_('Default port value for TCP connections.')
);
o.datatype = 'port';
o.default = '53';
o.depends({ check_type: '0' });
// icmp_packet_size
o = ss.option(form.ListValue,
'icmp_packet_size', _('ICMP packet data size'));
o.value(1, _('Small: 1 byte'));
o.value(32, _('Windows: 32 bytes'));
o.value(56, _('Standard: 56 bytes'));
o.value(248, _('Big: 248 bytes'));
o.value(1492, _('Huge: 1492 bytes'));
o.value(9000, _('Jumbo: 9000 bytes'));
o.default = '56';
o.depends({ check_type: '1' });
// iface
o = ss.option(widgets.DeviceSelect,
'iface', _('Interface'),
_('Network interface for Internet access. If not specified, the default interface is used.')
);
o.noaliases = true;
// interval_up
o = ss.option(form.ListValue,
'interval_up', _('Alive interval'),
_('Hosts polling interval when the Internet is up.')
);
makeUIIntervalOptions(o);
o.default = '6';
// interval_down
o = ss.option(form.ListValue,
'interval_down', _('Dead interval'),
_('Hosts polling interval when the Internet is down.')
);
makeUIIntervalOptions(o);
o.default = '1';
// connection_attempts
o = ss.option(form.ListValue,
'connection_attempts', _('Connection attempts'),
_('Maximum number of attempts to connect to each host.')
);
o.value(1);
o.value(2);
o.value(3);
o.default = '1';
// connection_timeout
o = ss.option(form.ListValue,
'connection_timeout', _('Connection timeout'),
_('Maximum timeout for waiting for a response from the host.')
);
o.value(1, '1 ' + _('sec'));
o.value(2, '2 ' + _('sec'));
o.value(3, '3 ' + _('sec'));
o.default = '1';
};
if(this.currentAppMode !== '0') {
poll.add(
@@ -1255,7 +1155,7 @@ return view.extend({
return mapPromise;
},
handleSaveApply: function(ev, mode) {
handleSaveApply(ev, mode) {
poll.stop();
return this.handleSave(ev).then(() => {
ui.changes.apply(mode == '0');

View File

@@ -1,6 +1,7 @@
'use strict';
'require baseclass';
'require fs';
'require rpc';
'require uci';
document.head.append(E('style', {'type': 'text/css'},
@@ -57,14 +58,22 @@ return baseclass.extend({
title : _('Internet'),
appName : 'internet-detector',
execPath : '/usr/bin/internet-detector',
uiCheckIntervalUp : null,
uiCheckIntervalDown : null,
currentAppMode : null,
inetStatus : null,
uiState : null,
counter : 0,
inetStatusFromJson : function(res) {
callUIPoll: rpc.declare({
object: 'luci.internet-detector',
method: 'UIPoll',
expect: { '': {} }
}),
getUIPoll() {
return this.callUIPoll().then(data => {
return data;
});
},
inetStatusFromJson(res) {
let inetStatData = null;
if(res.code === 0) {
try {
@@ -74,50 +83,38 @@ return baseclass.extend({
return inetStatData;
},
load: async function() {
if(!(this.uiCheckIntervalUp && this.uiCheckIntervalDown && this.currentAppMode)) {
async load() {
if(!this.currentAppMode) {
await uci.load(this.appName).then(data => {
this.uiCheckIntervalUp = Number(uci.get(this.appName, 'ui', 'interval_up'));
this.uiCheckIntervalDown = Number(uci.get(this.appName, 'ui', 'interval_down'));
this.currentAppMode = uci.get(this.appName, 'config', 'mode');
}).catch(e => {});
};
if(this.currentAppMode === '2') {
this.counter++;
if((this.uiState === 0 && this.counter % this.uiCheckIntervalUp) ||
(this.uiState === 1 && this.counter % this.uiCheckIntervalDown)
) {
return;
};
this.counter = 0;
return L.resolveDefault(fs.exec(this.execPath, [ 'poll' ]), null);
return this.getUIPoll();
}
else if(this.currentAppMode === '1') {
return L.resolveDefault(fs.exec(this.execPath, [ 'inet-status' ]), null);
};
},
render: function(data) {
render(data) {
if(this.currentAppMode === '0') {
return;
}
else if(this.currentAppMode === '1' && data) {
data = this.inetStatusFromJson(data);
};
if(data) {
this.inetStatus = this.inetStatusFromJson(data);
if(this.currentAppMode === '2') {
this.uiState = this.inetStatus.instances[0].inet;
};
};
this.inetStatus = data;
let inetStatusArea = E('div', {});
if(!this.inetStatus || !this.inetStatus.instances || this.inetStatus.instances.length === 0) {
inetStatusArea.append(
E('span', { 'class': 'id-label-status id-undefined' }, _('Undefined'))
);
let label = E('span', { 'class': 'id-label-status id-undefined' }, _('Undefined'));
if(this.currentAppMode === '2') {
label.classList.add('spinning');
};
inetStatusArea.append(label);
} else {
this.inetStatus.instances.sort((a, b) => a.num > b.num);
@@ -139,8 +136,7 @@ return baseclass.extend({
inetStatusArea.append(
E('span', { 'class': className }, '%s%s%s'.format(
(this.currentAppMode === '1') ? i.instance + ': ' : '',
status, publicIp)
i.instance + ': ', status, publicIp)
)
);
};

View File

@@ -434,9 +434,6 @@ msgstr "Таймаут между остановкой и запуском ин
msgid "Type a time string"
msgstr "Введите строку времени"
msgid "UI detector configuration"
msgstr "Конфигурация UI детектора"
msgid "Unable to read the contents"
msgstr "Невозможно прочитать содержимое"

View File

@@ -404,9 +404,6 @@ msgstr ""
msgid "Type a time string"
msgstr ""
msgid "UI detector configuration"
msgstr ""
msgid "Unable to read the contents"
msgstr ""

View File

@@ -0,0 +1,46 @@
#!/bin/sh
. /lib/functions.sh
. /usr/share/libubox/jshn.sh
readonly ID_EXEC="/usr/bin/internet-detector"
run_instance() {
config_get enabled "$1" enabled "0"
if [ $enabled = "1" ]; then
$ID_EXEC service "$1" > /dev/null 2>&1
fi
}
start_ui_instances() {
config_load internet-detector
config_get mode "config" mode "0"
if [ $mode = "2" ]; then
config_foreach run_instance "instance"
fi
}
ui_poll() {
$ID_EXEC uipoll
if [ $? -eq 126 ]; then
start_ui_instances
$ID_EXEC inet-status
fi
}
case "$1" in
list)
json_init
json_add_object "UIPoll"
json_close_object
json_dump
json_cleanup
;;
call)
case "$2" in
UIPoll)
ui_poll
;;
esac
;;
esac

View File

@@ -12,7 +12,8 @@
},
"uci": [ "internet-detector" ],
"ubus": {
"luci": [ "getInitList", "setInitAction" ]
"luci": [ "getInitList", "setInitAction" ],
"luci.internet-detector": [ "UIPoll" ]
}
},
"write": {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB