v0.4. Daemon modules, LED control

This commit is contained in:
gSpot
2021-12-08 20:58:14 +03:00
parent 54f13984a3
commit 29eb4e8a71
14 changed files with 451 additions and 249 deletions

View File

@@ -1,30 +1,38 @@
# Internet detector for OpenWrt. # Internet detector for OpenWrt.
Checking Internet availability. Internet-detector is an application for checking the availability of the Internet. Performs periodic connections to a known public host (8.8.8.8, 1.1.1.1) and determines the actual Internet availability.
OpenWrt >= 19.07. **OpenWrt** >= 19.07.
Dependences: lua, luci-lib-nixio, libuci-lua **Dependences:** lua, luci-lib-nixio, libuci-lua.
**Features:**
- It can run continuously as a system service or only in an open web interface.
- Checking the availability of a host using ping or by connecting via TCP to a specified port.
- Execution of custom shell scripts when connecting and disconnecting the Internet.
- LED indication of Internet availability.
![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/internet-led.jpg)
- The daemon is written entirely in Lua using the nixio library.
## Installation notes ## Installation notes
**OpenWrt >= 21.02:** **OpenWrt >= 21.02:**
wget --no-check-certificate -O /tmp/internet-detector_0.3.0-2_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector_0.3.0-2_all.ipk wget --no-check-certificate -O /tmp/internet-detector_0.4-1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector_0.4-1_all.ipk
opkg install /tmp/internet-detector_0.3.0-2_all.ipk opkg install /tmp/internet-detector_0.4-1_all.ipk
rm /tmp/internet-detector_0.3.0-2_all.ipk rm /tmp/internet-detector_0.4-1_all.ipk
/etc/init.d/internet-detector start /etc/init.d/internet-detector start
/etc/init.d/internet-detector enable /etc/init.d/internet-detector enable
wget --no-check-certificate -O /tmp/luci-app-internet-detector_0.3.0-3_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-app-internet-detector_0.3.0-3_all.ipk wget --no-check-certificate -O /tmp/luci-app-internet-detector_0.4-1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-app-internet-detector_0.4-1_all.ipk
opkg install /tmp/luci-app-internet-detector_0.3.0-3_all.ipk opkg install /tmp/luci-app-internet-detector_0.4-1_all.ipk
rm /tmp/luci-app-internet-detector_0.3.0-3_all.ipk rm /tmp/luci-app-internet-detector_0.4-1_all.ipk
/etc/init.d/rpcd restart /etc/init.d/rpcd restart
i18n-ru: i18n-ru:
wget --no-check-certificate -O /tmp/luci-i18n-internet-detector-ru_0.3.0-3_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-i18n-internet-detector-ru_0.3.0-3_all.ipk wget --no-check-certificate -O /tmp/luci-i18n-internet-detector-ru_0.4-1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-i18n-internet-detector-ru_0.4-1_all.ipk
opkg install /tmp/luci-i18n-internet-detector-ru_0.3.0-3_all.ipk opkg install /tmp/luci-i18n-internet-detector-ru_0.4-1_all.ipk
rm /tmp/luci-i18n-internet-detector-ru_0.3.0-3_all.ipk rm /tmp/luci-i18n-internet-detector-ru_0.4-1_all.ipk
**OpenWrt 19.07:** **OpenWrt 19.07:**
@@ -45,20 +53,6 @@ i18n-ru:
opkg install /tmp/luci-i18n-internet-detector-ru_0.3.0-2_all.ipk opkg install /tmp/luci-i18n-internet-detector-ru_0.3.0-2_all.ipk
rm /tmp/luci-i18n-internet-detector-ru_0.3.0-2_all.ipk rm /tmp/luci-i18n-internet-detector-ru_0.3.0-2_all.ipk
## Script for LED control:
![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/internet-led.jpg)
LED is on when Internet is available. A specific LED can be set in `/etc/internet-detector/run-script` (`LEDN`), either by number or by name from /sys/class/leds/*****. The list of available LEDs can be obtained using the command: `/usr/bin/internet-detector-led.sh list`.
wget --no-check-certificate -O /usr/bin/internet-detector-led.sh https://github.com/gSpotx2f/luci-app-internet-detector/raw/master/led/usr/bin/internet-detector-led.sh
chmod +x /usr/bin/internet-detector-led.sh
wget --no-check-certificate -O /etc/internet-detector/run-script https://github.com/gSpotx2f/luci-app-internet-detector/raw/master/led/etc/internet-detector/run-script
chmod +x /etc/internet-detector/run-script
uci set internet-detector.config.enable_run_script='1'
uci commit
/etc/init.d/internet-detector restart
## Screenshots: ## Screenshots:
![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/01.jpg) ![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/01.jpg)

View File

@@ -5,8 +5,8 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=internet-detector PKG_NAME:=internet-detector
PKG_VERSION:=0.3.0 PKG_VERSION:=0.4
PKG_RELEASE:=2 PKG_RELEASE:=1
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector> PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
@@ -39,6 +39,8 @@ endef
define Package/$(PKG_NAME)/install define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/bin $(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/files/usr/bin/internet-detector $(1)/usr/bin/internet-detector $(INSTALL_BIN) $(PKG_BUILD_DIR)/files/usr/bin/internet-detector $(1)/usr/bin/internet-detector
$(INSTALL_DIR) $(1)/usr/lib/internet-detector
$(INSTALL_DATA) $(PKG_BUILD_DIR)/files/usr/lib/internet-detector/mod_led_control.lua $(1)/usr/lib/internet-detector/mod_led_control.lua
$(INSTALL_DIR) $(1)/etc/internet-detector $(INSTALL_DIR) $(1)/etc/internet-detector
$(INSTALL_BIN) $(PKG_BUILD_DIR)/files/etc/internet-detector/down-script $(1)/etc/internet-detector/down-script $(INSTALL_BIN) $(PKG_BUILD_DIR)/files/etc/internet-detector/down-script $(1)/etc/internet-detector/down-script
$(INSTALL_BIN) $(PKG_BUILD_DIR)/files/etc/internet-detector/run-script $(1)/etc/internet-detector/run-script $(INSTALL_BIN) $(PKG_BUILD_DIR)/files/etc/internet-detector/run-script $(1)/etc/internet-detector/run-script

View File

@@ -1,18 +1,25 @@
config main 'config' config main 'config'
option mode '2' option mode '2'
list hosts '8.8.8.8'
list hosts '1.1.1.1'
option check_type '0'
option tcp_port '53'
config main 'ui_config'
option interval_up '6'
option interval_down '1'
option connection_attempts '1'
option connection_timeout '1'
config main 'service_config'
option interval_up '30'
option interval_down '5'
option connection_attempts '2'
option connection_timeout '2'
option enable_logger '1' option enable_logger '1'
option enable_up_script '0' option enable_up_script '0'
option enable_down_script '0' option enable_down_script '0'
option enable_run_script '0' option enable_run_script '0'
option interval_up '30'
option interval_down '5' config module 'mod_led_control'
option ui_interval_up '6' option enabled '0'
option ui_interval_down '1'
list hosts '8.8.8.8'
list hosts '1.1.1.1'
option check_type '0'
option connection_attempts '2'
option connection_timeout '2'
option ui_connection_attempts '1'
option ui_connection_timeout '1'
option tcp_port '53'

View File

@@ -35,11 +35,13 @@ local Config = {
["connectionTimeout"] = 3, ["connectionTimeout"] = 3,
["UIConnectionTimeout"] = 1, ["UIConnectionTimeout"] = 1,
["tcpPort"] = 53, ["tcpPort"] = 53,
["checkType"] = 0, -- 0: ping, 1: TCP ["checkType"] = 0, -- 0: TCP, 1: ping
["loggerLevel"] = "info", ["loggerLevel"] = "info",
--["loggerCmd"] = "logger", --["loggerCmd"] = "logger",
["modules"] = {},
} }
Config.configDir = "/etc/" .. Config.appName Config.configDir = "/etc/" .. Config.appName
Config.modulesDir = "/usr/lib/" .. Config.appName
Config.upScript = Config.configDir .. "/" .. "up-script" Config.upScript = Config.configDir .. "/" .. "up-script"
Config.downScript = Config.configDir .. "/" .. "down-script" Config.downScript = Config.configDir .. "/" .. "down-script"
Config.runScript = Config.configDir .. "/" .. "run-script" Config.runScript = Config.configDir .. "/" .. "run-script"
@@ -59,30 +61,28 @@ if not nixio then
end end
local uci = prequire("uci") local uci = prequire("uci")
if uci then if not uci then
error("You need to install libuci-lua...")
-- Load settings from UCI
local cursor = uci.cursor()
Config.mode = cursor:get(Config.appName, "config", "mode")
Config.enableLogger = cursor:get(Config.appName, "config", "enable_logger")
Config.enableUpScript = cursor:get(Config.appName, "config", "enable_up_script")
Config.enableDownScript = cursor:get(Config.appName, "config", "enable_down_script")
Config.enableRunScript = cursor:get(Config.appName, "config", "enable_run_script")
Config.intervalUp = tonumber(cursor:get(Config.appName, "config", "interval_up"))
Config.intervalDown = tonumber(cursor:get(Config.appName, "config", "interval_down"))
Config.hosts = cursor:get(Config.appName, "config", "hosts")
Config.checkType = tonumber(cursor:get(Config.appName, "config", "check_type"))
Config.connectionAttempts = tonumber(cursor:get(Config.appName, "config", "connection_attempts"))
Config.connectionTimeout = tonumber(cursor:get(Config.appName, "config", "connection_timeout"))
Config.UIConnectionAttempts = tonumber(cursor:get(Config.appName, "config", "ui_connection_attempts"))
Config.UIConnectionTimeout = tonumber(cursor:get(Config.appName, "config", "ui_connection_timeout"))
Config.tcpPort = tonumber(cursor:get(Config.appName, "config", "tcp_port"))
else
io.stderr:write("libuci-lua does not exists! The default settings will be used...\n")
end end
-- Load settings from UCI
local uciCursor = uci.cursor()
Config.mode = uciCursor:get(Config.appName, "config", "mode")
Config.hosts = uciCursor:get(Config.appName, "config", "hosts")
Config.checkType = tonumber(uciCursor:get(Config.appName, "config", "check_type"))
Config.tcpPort = tonumber(uciCursor:get(Config.appName, "config", "tcp_port"))
Config.UIConnectionAttempts = tonumber(uciCursor:get(Config.appName, "ui_config", "connection_attempts"))
Config.UIConnectionTimeout = tonumber(uciCursor:get(Config.appName, "ui_config", "connection_timeout"))
Config.enableLogger = uciCursor:get(Config.appName, "service_config", "enable_logger")
Config.enableUpScript = uciCursor:get(Config.appName, "service_config", "enable_up_script")
Config.enableDownScript = uciCursor:get(Config.appName, "service_config", "enable_down_script")
Config.enableRunScript = uciCursor:get(Config.appName, "service_config", "enable_run_script")
Config.intervalUp = tonumber(uciCursor:get(Config.appName, "service_config", "interval_up"))
Config.intervalDown = tonumber(uciCursor:get(Config.appName, "service_config", "interval_down"))
Config.connectionAttempts = tonumber(uciCursor:get(Config.appName, "service_config", "connection_attempts"))
Config.connectionTimeout = tonumber(uciCursor:get(Config.appName, "service_config", "connection_timeout"))
local function writeValueToFile(filePath, str) local function writeValueToFile(filePath, str)
local retValue = false local retValue = false
local fh = io.open(filePath, "w") local fh = io.open(filePath, "w")
@@ -114,6 +114,28 @@ local function writeLogMessage(level, msg)
end end
end end
local function loadModules()
package.path = string.format("%s;%s/?.lua", package.path, Config.modulesDir)
Config.modules = {}
uciCursor:foreach(
Config.appName,
"module",
function(s)
local mod_name = s[".name"]
if mod_name and s.enabled == "1" then
local m = prequire(mod_name)
if m then
m.syslog = writeLogMessage
m.writeValue = writeValueToFile
m.readValue = readValueFromFile
m:init(s)
Config.modules[#Config.modules + 1] = m
end
end
end
)
end
local function runExternalScript(scriptPath, inetStat) local function runExternalScript(scriptPath, inetStat)
if inetStat == nil then if inetStat == nil then
inetStat = "" inetStat = ""
@@ -164,7 +186,7 @@ local function tcpConnectToHost(host, port)
end end
local function checkHosts() local function checkHosts()
local checkFunc = (Config.checkType == 1) and tcpConnectToHost or pingHost local checkFunc = (Config.checkType == 1) and pingHost or tcpConnectToHost
local retCode = 1 local retCode = 1
for k, v in ipairs(Config.parsedHosts) do for k, v in ipairs(Config.parsedHosts) do
for i = 1, Config.connectionAttempts do for i = 1, Config.connectionAttempts do
@@ -181,20 +203,20 @@ local function checkHosts()
end end
local function main() local function main()
local last_status local lastStatus
local current_status local currentStatus
local interval = Config.intervalUp local interval = Config.intervalUp
while true do while true do
current_status = checkHosts() currentStatus = checkHosts()
if not nixio.fs.access(Config.statusFile, "r") then if not nixio.fs.access(Config.statusFile, "r") then
writeValueToFile(Config.statusFile, current_status) writeValueToFile(Config.statusFile, currentStatus)
end end
if current_status == 0 then if currentStatus == 0 then
interval = Config.intervalUp interval = Config.intervalUp
if last_status ~= nil and current_status ~= last_status then if lastStatus ~= nil and currentStatus ~= lastStatus then
writeValueToFile(Config.statusFile, current_status) writeValueToFile(Config.statusFile, currentStatus)
writeLogMessage("notice", "internet connected") writeLogMessage("notice", "internet connected")
if Config.enableUpScript == "1" then if Config.enableUpScript == "1" then
runExternalScript(Config.upScript) runExternalScript(Config.upScript)
@@ -202,8 +224,8 @@ local function main()
end end
else else
interval = Config.intervalDown interval = Config.intervalDown
if last_status ~= nil and current_status ~= last_status then if lastStatus ~= nil and currentStatus ~= lastStatus then
writeValueToFile(Config.statusFile, current_status) writeValueToFile(Config.statusFile, currentStatus)
writeLogMessage("notice", "internet disconnected") writeLogMessage("notice", "internet disconnected")
if Config.enableDownScript == "1" then if Config.enableDownScript == "1" then
runExternalScript(Config.downScript) runExternalScript(Config.downScript)
@@ -211,11 +233,15 @@ local function main()
end end
end end
if Config.enableRunScript == "1" then for _, e in ipairs(Config.modules) do
runExternalScript(Config.runScript, current_status) e:run(currentStatus, lastStatus)
end end
last_status = current_status if Config.enableRunScript == "1" then
runExternalScript(Config.runScript, currentStatus)
end
lastStatus = currentStatus
nixio.nanosleep(interval) nixio.nanosleep(interval)
end end
end end
@@ -312,6 +338,19 @@ local function run()
local pidValue = nixio.getpid() local pidValue = nixio.getpid()
writeValueToFile(Config.pidFile, pidValue) writeValueToFile(Config.pidFile, pidValue)
writeLogMessage("info", "started") writeLogMessage("info", "started")
loadModules()
-- Loaded modules
local modules = {}
for _, v in ipairs(Config.modules) do
modules[#modules + 1] = string.format("%s", v.name)
end
if #modules > 0 then
writeLogMessage(
"info", string.format("Loaded modules: %s", table.concat(modules, ", "))
)
end
main() main()
end end

View File

@@ -0,0 +1,81 @@
local nixio = require("nixio")
local Module = {
name = "mod_led_control",
sysLedsDir = "/sys/class/leds",
syslog = function(level, msg) return true end,
writeValue = function(filePath, str) return false end,
readValue = function(filePath) return nil end,
ledName = nil,
_enabled = false,
_ledDir = nil,
_ledMaxBrightnessFile = nil,
_ledBrightnessFile = nil,
_ledMaxBrightness = nil,
}
function Module:resetLeds()
local dir = nixio.fs.dir(self.sysLedsDir)
if not dir then
return
end
for led in dir do
local brightness = string.format("%s/%s/brightness", self.sysLedsDir, led)
if nixio.fs.access(brightness, "w") then
self.writeValue(brightness, 0)
end
end
end
function Module:init(t)
self.ledName = t.led_name
if not self.ledName then
return
end
self._ledDir = string.format("%s/%s", self.sysLedsDir, self.ledName)
self._ledMaxBrightnessFile = self._ledDir .. "/max_brightness"
self._ledBrightnessFile = self._ledDir .. "/brightness"
self._ledMaxBrightness = self.readValue(self._ledMaxBrightnessFile) or 1
if (not nixio.fs.access(self._ledDir, "r") or
not nixio.fs.access(self._ledBrightnessFile, "r", "w")) then
self._enabled = false
self.syslog("warning", string.format('%s: "%s" is not available', self.name, self.ledName))
else
self._enabled = true
-- Reset all LEDs
--self:resetLeds()
end
end
function Module:getCurrentState()
local state = self.readValue(self._ledBrightnessFile)
if state and tonumber(state) > 0 then
return tonumber(state)
end
end
function Module:on()
self.writeValue(self._ledBrightnessFile, self._ledMaxBrightness)
end
function Module:off()
self.writeValue(self._ledBrightnessFile, 0)
end
function Module:run(currentStatus, lastStatus)
if not self._enabled then
return
end
if currentStatus == 0 then
if not self:getCurrentState() then
self:on()
end
else
if self:getCurrentState() then
self:off()
end
end
end
return Module

View File

@@ -1,14 +0,0 @@
# Shell commands that are executed every time the Internet is checked for availability
#
# $1 : (0|1) - internet status: 0 is up, 1 is down
#
LEDN=1
LED_CMD="/usr/bin/internet-detector-led.sh"
LED_STATE=`$LED_CMD state $LEDN`
if [ $LED_STATE -eq 0 -a $1 -eq 0 ]; then
$LED_CMD on $LEDN
elif [ $LED_STATE -ne 0 -a $1 -eq 1 ]; then
$LED_CMD off $LEDN
fi

View File

@@ -1,63 +0,0 @@
#/bin/sh
#
# Usage: internet-detector-led.sh on|off|state|list [<LED number>|<LED sysfs-name>]
#
# Examples:
# internet-detector-led.sh list # list of available LEDs
# internet-detector-led.sh on 2 # turn on LED 2
# internet-detector-led.sh off 2 # turn off LED 2
# internet-detector-led.sh on "nbg6817:white:internet" # turn on LED by sysfs-name (/sys/class/leds/nbg6817:white:internet)
# internet-detector-led.sh off "nbg6817:white:internet" # turn off --"--
# internet-detector-led.sh on # same as "internet-detector-led.sh on 1" (default <LED number> is 1)
# internet-detector-led.sh off # turn off --"--
# internet-detector-led.sh state 2 # current state (brightness) of LED 2
# ...
#
if [ -n $2 ]; then
LEDN=$2
else
LEDN=1
fi
SYSFS_LEDS="/sys/class/leds/"
LED="`ls -1 $SYSFS_LEDS | awk -v LEDN=$LEDN '{
LEDN = (length(LEDN) == 0) ? 1 : LEDN;
if($0 == LEDN || NR == LEDN) {
print $0;
exit;
}
}'`" 2> /dev/null
LED_BR_PATH="${SYSFS_LEDS}/${LED}/brightness"
[ -w $LED_BR_PATH ] || exit 1
MAX_BRIGHTNESS=`cat ${SYSFS_LEDS}/${LED}/max_brightness` 2> /dev/null
if [ -z $MAX_BRIGHTNESS ]; then
MAX_BRIGHTNESS=1
fi
case $1 in
on)
printf $MAX_BRIGHTNESS > $LED_BR_PATH
;;
off)
printf 0 > $LED_BR_PATH
;;
state)
cat $LED_BR_PATH 2> /dev/null
;;
list)
ls -1 $SYSFS_LEDS | awk '{print NR ": " $0}'
;;
*)
echo "Usage: `basename $0` on|off|state|list [<LED number>|<LED sysfs-name>]" >&2
exit 1
;;
esac
exit 0;

View File

@@ -4,7 +4,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_VERSION:=0.3.0-3 PKG_VERSION:=0.4-1
LUCI_TITLE:=LuCI support for internet-detector LUCI_TITLE:=LuCI support for internet-detector
LUCI_DEPENDS:=+internet-detector LUCI_DEPENDS:=+internet-detector
LUCI_PKGARCH:=all LUCI_PKGARCH:=all

View File

@@ -17,6 +17,7 @@ return view.extend({
upScriptPath : '/etc/internet-detector/up-script', upScriptPath : '/etc/internet-detector/up-script',
downScriptPath : '/etc/internet-detector/down-script', downScriptPath : '/etc/internet-detector/down-script',
runScriptPath : '/etc/internet-detector/run-script', runScriptPath : '/etc/internet-detector/run-script',
ledsPath : '/sys/class/leds',
pollInterval : L.env.pollinterval, pollInterval : L.env.pollinterval,
appStatus : 'stoped', appStatus : 'stoped',
initStatus : null, initStatus : null,
@@ -31,6 +32,7 @@ return view.extend({
uiCheckIntervalUp : null, uiCheckIntervalUp : null,
uiCheckIntervalDown : null, uiCheckIntervalDown : null,
currentAppMode : '0', currentAppMode : '0',
leds : null,
callInitStatus: rpc.declare({ callInitStatus: rpc.declare({
object: 'luci', object: 'luci',
@@ -202,6 +204,20 @@ return view.extend({
}; };
}, },
CBIBlockTitle: form.DummyValue.extend({
string: null,
renderWidget: function(section_id, option_index, cfgvalue) {
this.title = this.description = null;
return E([
E('label', { 'class': 'cbi-value-title' }),
E('div', { 'class': 'cbi-value-field' },
E('b', {}, this.string)
),
]);
},
}),
CBIBlockService: form.DummyValue.extend({ CBIBlockService: form.DummyValue.extend({
ctx: null, ctx: null,
@@ -339,6 +355,7 @@ return view.extend({
return Promise.all([ return Promise.all([
fs.exec(this.execPath, [ 'status' ]), fs.exec(this.execPath, [ 'status' ]),
this.getInitStatus(), this.getInitStatus(),
fs.list(this.ledsPath),
uci.load('internet-detector'), uci.load('internet-detector'),
]).catch(e => { ]).catch(e => {
ui.addNotification(null, E('p', _('An error has occurred') + ': %s'.format(e.message))); ui.addNotification(null, E('p', _('An error has occurred') + ': %s'.format(e.message)));
@@ -351,9 +368,10 @@ return view.extend({
}; };
this.appStatus = (data[0].code === 0) ? data[0].stdout.trim() : null; this.appStatus = (data[0].code === 0) ? data[0].stdout.trim() : null;
this.initStatus = data[1]; this.initStatus = data[1];
this.leds = data[2];
this.currentAppMode = uci.get('internet-detector', 'config', 'mode'); this.currentAppMode = uci.get('internet-detector', 'config', 'mode');
this.uiCheckIntervalUp = Number(uci.get('internet-detector', 'config', 'ui_interval_up')); this.uiCheckIntervalUp = Number(uci.get('internet-detector', 'ui_config', 'interval_up'));
this.uiCheckIntervalDown = Number(uci.get('internet-detector', 'config', 'ui_interval_down')); this.uiCheckIntervalDown = Number(uci.get('internet-detector', 'ui_config', 'interval_down'));
let upScriptEditDialog = new this.fileEditDialog( let upScriptEditDialog = new this.fileEditDialog(
this.upScriptPath, this.upScriptPath,
@@ -371,54 +389,57 @@ return view.extend({
_("Shell commands that are executed every time the Internet is checked for availability"), _("Shell commands that are executed every time the Internet is checked for availability"),
); );
let m, s, o;
m = new form.Map('internet-detector', _('Internet detector'), /* UCI sections */
_('Checking Internet availability.'));
s = m.section(form.NamedSection, 'config'); let s, o;
s.anonymous = true;
s.addremove = false;
s.tab('main_settings', _('Main settings')); //// Main configuration
// service section let mMain = new form.Map('internet-detector');
o = s.taboption('main_settings', this.CBIBlockService, '_dummy_service'); s = mMain.section(form.NamedSection, 'config');
// service widget
o = s.option(this.CBIBlockService, '_dummy_service');
o.ctx = this; o.ctx = this;
// mode // mode
o = s.taboption('main_settings', form.ListValue, o = s.option(form.ListValue,
'mode', _('Internet detector mode')); 'mode', _('Internet detector mode'));
o.value('0', _('Disabled')); o.value('0', _('Disabled'));
o.value('1', _('Web UI only')); o.value('1', _('Web UI only'));
o.value('2', _('Service')); o.value('2', _('Service'));
o.description = '%s;<br>%s;<br>%s;'.format( o.description = '%s;<br />%s;<br />%s;'.format(
_('Disabled: detector is completely off'), _('Disabled: detector is completely off'),
_('Web UI only: detector works only when the Web UI is open (UI detector)'), _('Web UI only: detector works only when the Web UI is open (UI detector)'),
_('Service: detector always runs as a system service') _('Service: detector always runs as a system service')
); );
// hosts // hosts
o = s.taboption('main_settings', form.DynamicList, o = s.option(form.DynamicList,
'hosts', _('Hosts')); 'hosts', _('Hosts'));
o.description = _('Hosts to check Internet availability. Hosts are polled (in list order) until at least one of them responds'); o.description = _('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(host,hostport)';
// check_type // check_type
o = s.taboption('main_settings', form.ListValue, o = s.option(form.ListValue,
'check_type', _('Check type')); 'check_type', _('Check type'));
o.description = _('Host availability check type'); o.description = _('Host availability check type');
o.value(0, _('Ping host')); o.value(0, _('TCP port connection'));
o.value(1, _('TCP port connection')); o.value(1, _('Ping host'));
// tcp_port // tcp_port
o = s.taboption('main_settings', form.Value, o = s.option(form.Value,
'tcp_port', _('TCP port')); 'tcp_port', _('TCP port'));
o.description = _('Default port value for TCP connections'); o.description = _('Default port value for TCP connections');
o.rmempty = false; o.rmempty = false;
o.datatype = "port"; o.datatype = "port";
s.tab('ui_detector_configuration', _('UI detector configuration'));
//// UI detector configuration
let mUi = new form.Map('internet-detector');
s = mUi.section(form.NamedSection, 'ui_config');
let makeUIIntervalOptions = L.bind(function(list) { let makeUIIntervalOptions = L.bind(function(list) {
list.value(1, '%d %s'.format(this.pollInterval, _('sec'))); list.value(1, '%d %s'.format(this.pollInterval, _('sec')));
@@ -429,80 +450,39 @@ return view.extend({
list.value(6, '%d %s'.format(this.pollInterval * 6, _('sec'))); list.value(6, '%d %s'.format(this.pollInterval * 6, _('sec')));
}, this); }, this);
// ui_interval_up // interval_up
o = s.taboption('ui_detector_configuration', form.ListValue, o = s.option(form.ListValue,
'ui_interval_up', _('Alive interval')); 'interval_up', _('Alive interval'));
o.description = _('Hosts polling interval when the Internet is up'); o.description = _('Hosts polling interval when the Internet is up');
makeUIIntervalOptions(o); makeUIIntervalOptions(o);
// ui_interval_down // interval_down
o = s.taboption('ui_detector_configuration', form.ListValue, o = s.option(form.ListValue,
'ui_interval_down', _('Dead interval')); 'interval_down', _('Dead interval'));
o.description = _('Hosts polling interval when the Internet is down'); o.description = _('Hosts polling interval when the Internet is down');
makeUIIntervalOptions(o); makeUIIntervalOptions(o);
// ui_connection_attempts // connection_attempts
o = s.taboption('ui_detector_configuration', form.ListValue, o = s.option(form.ListValue,
'ui_connection_attempts', _('Connection attempts')); 'connection_attempts', _('Connection attempts'));
o.description = _('Maximum number of attempts to connect to each host'); o.description = _('Maximum number of attempts to connect to each host');
o.value(1); o.value(1);
o.value(2); o.value(2);
o.value(3); o.value(3);
// ui_connection_timeout // connection_timeout
o = s.taboption('ui_detector_configuration', form.ListValue, o = s.option(form.ListValue,
'ui_connection_timeout', _('Connection timeout')); 'connection_timeout', _('Connection timeout'));
o.description = _('Maximum timeout for waiting for a response from the host'); o.description = _('Maximum timeout for waiting for a response from the host');
o.value(1, "1 " + _('sec')); o.value(1, "1 " + _('sec'));
o.value(2, "2 " + _('sec')); o.value(2, "2 " + _('sec'));
o.value(3, "3 " + _('sec')); o.value(3, "3 " + _('sec'));
s.tab('service_configuration', _('Service configuration'));
// enable_logger //// Service configuration
o = s.taboption('service_configuration', form.Flag,
'enable_logger', _('Enable logging'));
o.description = _('Write messages to the system log');
o.rmempty = false;
// enable_up_script let mService = new form.Map('internet-detector');
o = s.taboption('service_configuration', form.Flag, s = mService.section(form.NamedSection, 'service_config');
'enable_up_script', _('Enable up-script'));
o.description = _('Execute commands when the Internet is connected');
o.rmempty = false;
// up_script edit dialog
o = s.taboption('service_configuration', form.Button,
'_up_script_btn', _('Edit up-script'));
o.onclick = () => upScriptEditDialog.show();
o.inputtitle = _('Edit');
o.inputstyle = 'edit btn';
// enable_down_script
o = s.taboption('service_configuration', form.Flag,
'enable_down_script', _('Enable down-script'));
o.description = _('Execute commands when the Internet is disconnected');
o.rmempty = false;
// down_script edit dialog
o = s.taboption('service_configuration', form.Button,
'_down_script_btn', _('Edit down-script'));
o.onclick = () => downScriptEditDialog.show();
o.inputtitle = _('Edit');
o.inputstyle = 'edit btn';
// enable_run_script
o = s.taboption('service_configuration', form.Flag,
'enable_run_script', _('Enable run-script'));
o.description = _('Execute commands every time the Internet is checked for availability');
o.rmempty = false;
// run_script edit dialog
o = s.taboption('service_configuration', form.Button,
'_run_script_btn', _('Edit run-script'));
o.onclick = () => runScriptEditDialog.show();
o.inputtitle = _('Edit');
o.inputstyle = 'edit btn';
function makeIntervalOptions(list) { function makeIntervalOptions(list) {
list.value(2, '2 ' + _('sec')); list.value(2, '2 ' + _('sec'));
@@ -519,19 +499,19 @@ return view.extend({
} }
// interval_up // interval_up
o = s.taboption('service_configuration', form.ListValue, o = s.option(form.ListValue,
'interval_up', _('Alive interval')); 'interval_up', _('Alive interval'));
o.description = _('Hosts polling interval when the Internet is up'); o.description = _('Hosts polling interval when the Internet is up');
makeIntervalOptions(o); makeIntervalOptions(o);
// interval_down // interval_down
o = s.taboption('service_configuration', form.ListValue, o = s.option(form.ListValue,
'interval_down', _('Dead interval')); 'interval_down', _('Dead interval'));
o.description = _('Hosts polling interval when the Internet is down'); o.description = _('Hosts polling interval when the Internet is down');
makeIntervalOptions(o); makeIntervalOptions(o);
// connection_attempts // connection_attempts
o = s.taboption('service_configuration', form.ListValue, o = s.option(form.ListValue,
'connection_attempts', _('Connection attempts')); 'connection_attempts', _('Connection attempts'));
o.description = _('Maximum number of attempts to connect to each host'); o.description = _('Maximum number of attempts to connect to each host');
o.value(1); o.value(1);
@@ -541,7 +521,7 @@ return view.extend({
o.value(5); o.value(5);
// connection_timeout // connection_timeout
o = s.taboption('service_configuration', form.ListValue, o = s.option( form.ListValue,
'connection_timeout', _('Connection timeout')); 'connection_timeout', _('Connection timeout'));
o.description = _('Maximum timeout for waiting for a response from the host'); o.description = _('Maximum timeout for waiting for a response from the host');
o.value(1, "1 " + _('sec')); o.value(1, "1 " + _('sec'));
@@ -555,20 +535,153 @@ return view.extend({
o.value(9, "9 " + _('sec')); o.value(9, "9 " + _('sec'));
o.value(10, "10 " + _('sec')); o.value(10, "10 " + _('sec'));
if(this.currentAppMode !== '0') { // enable_logger
poll.add( o = s.option(form.Flag,
L.bind((this.currentAppMode === '2') ? this.servicePoll : this.uiPoll, this), 'enable_logger', _('Enable logging'));
this.pollInterval o.description = _('Write messages to the system log');
); o.rmempty = false;
// enable_up_script
o = s.option(form.Flag,
'enable_up_script', _('Enable up-script'));
o.description = _('Execute commands when the Internet is connected');
o.rmempty = false;
// up_script edit dialog
o = s.option(form.Button,
'_up_script_btn', _('Edit up-script'));
o.onclick = () => upScriptEditDialog.show();
o.inputtitle = _('Edit');
o.inputstyle = 'edit btn';
// enable_down_script
o = s.option(form.Flag,
'enable_down_script', _('Enable down-script'));
o.description = _('Execute commands when the Internet is disconnected');
o.rmempty = false;
// down_script edit dialog
o = s.option(form.Button,
'_down_script_btn', _('Edit down-script'));
o.onclick = () => downScriptEditDialog.show();
o.inputtitle = _('Edit');
o.inputstyle = 'edit btn';
// enable_run_script
o = s.option(form.Flag,
'enable_run_script', _('Enable run-script'));
o.description = _('Execute commands every time the Internet is checked for availability');
o.rmempty = false;
// run_script edit dialog
o = s.option(form.Button,
'_run_script_btn', _('Edit run-script'));
o.onclick = () => runScriptEditDialog.show();
o.inputtitle = _('Edit');
o.inputstyle = 'edit btn';
/* Modules */
//// LED control
let mLed = new form.Map('internet-detector');
s = mLed.section(form.NamedSection, 'mod_led_control');
o = s.option(this.CBIBlockTitle, '_dummy');
o.string = _('<abbr title="Light Emitting Diode">LED</abbr> control') + ':';
if(this.leds && this.leds.length > 0) {
// enabled
o = s.option(form.Flag, 'enabled',
_('Enable <abbr title="Light Emitting Diode">LED</abbr> control'));
o.rmempty = false;
o.description = _('<abbr title="Light Emitting Diode">LED</abbr> is on when Internet is available.');
// led_name
o = s.option(form.ListValue, 'led_name',
_('<abbr title="Light Emitting Diode">LED</abbr> Name'));
o.depends('enabled', '1');
this.leds.sort((a, b) => a.name > b.name);
this.leds.forEach(e => o.value(e.name));
} else {
o = s.option(form.DummyValue, '_dummy');
o.rawhtml = true;
o.default = '<label class="cbi-value-title"></label><div class="cbi-value-field"><em>' +
_('No <abbr title="Light Emitting Diode">LED</abbr>s available...') +
'</em></div>';
}; };
let mapPromise = m.render();
mapPromise.then(node => node.classList.add('fade-in')); /* Rendering */
return mapPromise;
let settingsNode = E('div', { 'class': 'cbi-section fade-in' },
E('div', { 'class': 'cbi-section-node' },
E('div', { 'class': 'cbi-value' },
E('em', { 'class': 'spinning' }, _('Collecting data...'))
)
)
);
let promises = [ mMain.render(), mUi.render(), mService.render() ];
if(mLed) {
promises.push(mLed.render());
};
Promise.all(promises).then(maps => {
let settingsTabs = E('div', { 'class': 'cbi-section fade-in' });
let tabsContainer = E('div', { 'class': 'cbi-section-node cbi-section-node-tabbed' });
settingsTabs.append(tabsContainer);
// Main settings tab
let mainTab = E('div', {
'data-tab' : 0,
'data-tab-title': _('Main settings'),
}, maps[0]);
tabsContainer.append(mainTab);
// UI detector configuration tab
let uiTab = E('div', {
'data-tab' : 1,
'data-tab-title': _('UI detector configuration'),
}, maps[1]);
tabsContainer.append(uiTab);
// Service configuration tab
let serviceTab = E('div', {
'data-tab' : 2,
'data-tab-title': _('Service configuration'),
}, maps[2]);
// LED control
if(maps[3]) {
serviceTab.append(maps[3]);
};
tabsContainer.append(serviceTab);
ui.tabs.initTabGroup(tabsContainer.children);
settingsNode.replaceWith(settingsTabs);
if(this.currentAppMode !== '0') {
poll.add(
L.bind((this.currentAppMode === '2') ? this.servicePoll : this.uiPoll, this),
this.pollInterval
);
};
}).catch(e => ui.addNotification(null, E('p', {}, e.message)));
return E([
E('h2', { 'class': 'fade-in' }, _('Internet detector')),
E('div', { 'class': 'cbi-section-descr fade-in' },
_('Checking Internet availability.')),
settingsNode,
]);
}, },
handleSaveApply: function(ev, mode) { handleSaveApply: function(ev, mode) {
return this.handleSave(ev).then(() => { return this.handleSave(ev).then(() => {
ui.changes.apply(mode == '0'); ui.changes.apply(mode == '0');
window.setTimeout(() => this.serviceRestart(), 3000); window.setTimeout(() => this.serviceRestart(), 3000);
}); });

View File

@@ -15,8 +15,8 @@ return baseclass.extend({
'currentAppMode' in window 'currentAppMode' in window
)) { )) {
await uci.load('internet-detector').then(data => { await uci.load('internet-detector').then(data => {
window.uiCheckIntervalUp = Number(uci.get('internet-detector', 'config', 'ui_interval_up')); window.uiCheckIntervalUp = Number(uci.get('internet-detector', 'ui_config', 'interval_up'));
window.uiCheckIntervalDown = Number(uci.get('internet-detector', 'config', 'ui_interval_down')); window.uiCheckIntervalDown = Number(uci.get('internet-detector', 'ui_config', 'interval_down'));
window.currentAppMode = uci.get('internet-detector', 'config', 'mode'); window.currentAppMode = uci.get('internet-detector', 'config', 'mode');
}).catch(e => {}); }).catch(e => {});
}; };

View File

@@ -24,12 +24,18 @@ msgstr "Тип проверки"
msgid "Checking Internet availability." msgid "Checking Internet availability."
msgstr "Проверка доступности Интернет." msgstr "Проверка доступности Интернет."
msgid "Collecting data..."
msgstr "Сбор данных..."
msgid "Command failed" msgid "Command failed"
msgstr "Команда не выполнена" msgstr "Команда не выполнена"
msgid "Connected" msgid "Connected"
msgstr "Подключен" msgstr "Подключен"
msgid "Connection attempts"
msgstr "Попытки подключения"
msgid "Connection timeout" msgid "Connection timeout"
msgstr "Таймаут соединения" msgstr "Таймаут соединения"
@@ -55,7 +61,7 @@ msgid "Disconnected"
msgstr "Отключен" msgstr "Отключен"
msgid "Dismiss" msgid "Dismiss"
msgstr "Отмена" msgstr "Закрыть"
msgid "Edit" msgid "Edit"
msgstr "Изменить" msgstr "Изменить"
@@ -73,7 +79,7 @@ msgid "Enable down-script"
msgstr "Включить down-script" msgstr "Включить down-script"
msgid "Enable logging" msgid "Enable logging"
msgstr "Включить логирование" msgstr "Включить запись событий в лог"
msgid "Enable run-script" msgid "Enable run-script"
msgstr "Включить run-script" msgstr "Включить run-script"
@@ -218,3 +224,18 @@ msgstr "сек"
msgid "up-script" msgid "up-script"
msgstr "" msgstr ""
msgid "<abbr title=\"Light Emitting Diode\">LED</abbr> control"
msgstr "Управление <abbr title=\"Светодиод\">LED</abbr>"
msgid "<abbr title=\"Light Emitting Diode\">LED</abbr> is on when Internet is available."
msgstr "<abbr title=\"Светодиод\">LED</abbr> включен если Интернет доступен."
msgid "<abbr title=\"Light Emitting Diode\">LED</abbr> Name"
msgstr "Имя <abbr title=\"Светодиод\">LED</abbr>"
msgid "Enable <abbr title=\"Light Emitting Diode\">LED</abbr> control"
msgstr "Включить управление <abbr title=\"Светодиод\">LED</abbr>"
msgid "No <abbr title=\"Light Emitting Diode\">LED</abbr>s available..."
msgstr "Нет доступных <abbr title=\"Светодиод\">LED</abbr>..."

View File

@@ -13,12 +13,18 @@ msgstr ""
msgid "Checking Internet availability." msgid "Checking Internet availability."
msgstr "" msgstr ""
msgid "Collecting data..."
msgstr ""
msgid "Command failed" msgid "Command failed"
msgstr "" msgstr ""
msgid "Connected" msgid "Connected"
msgstr "" msgstr ""
msgid "Connection attempts"
msgstr ""
msgid "Connection timeout" msgid "Connection timeout"
msgstr "" msgstr ""
@@ -204,3 +210,18 @@ msgstr ""
msgid "up-script" msgid "up-script"
msgstr "" msgstr ""
msgid "<abbr title=\"Light Emitting Diode\">LED</abbr> control"
msgstr ""
msgid "<abbr title=\"Light Emitting Diode\">LED</abbr> is on when Internet is available."
msgstr ""
msgid "<abbr title=\"Light Emitting Diode\">LED</abbr> Name"
msgstr ""
msgid "Enable <abbr title=\"Light Emitting Diode\">LED</abbr> control"
msgstr ""
msgid "No <abbr title=\"Light Emitting Diode\">LED</abbr>s available..."
msgstr ""

View File

@@ -3,6 +3,7 @@
"description": "Grant access to internet-detector procedures", "description": "Grant access to internet-detector procedures",
"read": { "read": {
"file": { "file": {
"/sys/class/leds": [ "list" ],
"/etc/internet-detector/up-script": [ "read" ], "/etc/internet-detector/up-script": [ "read" ],
"/etc/internet-detector/down-script": [ "read" ], "/etc/internet-detector/down-script": [ "read" ],
"/etc/internet-detector/run-script": [ "read" ], "/etc/internet-detector/run-script": [ "read" ],

Binary file not shown.

Before

Width:  |  Height:  |  Size: 199 KiB

After

Width:  |  Height:  |  Size: 155 KiB