mirror of
https://github.com/gSpotx2f/luci-app-internet-detector.git
synced 2025-12-06 19:46:51 +03:00
v0.4. Daemon modules, LED control
This commit is contained in:
46
README.md
46
README.md
@@ -1,30 +1,38 @@
|
||||
# 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.
|
||||

|
||||
- The daemon is written entirely in Lua using the nixio library.
|
||||
|
||||
## Installation notes
|
||||
|
||||
**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
|
||||
opkg install /tmp/internet-detector_0.3.0-2_all.ipk
|
||||
rm /tmp/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.4-1_all.ipk
|
||||
rm /tmp/internet-detector_0.4-1_all.ipk
|
||||
/etc/init.d/internet-detector start
|
||||
/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
|
||||
opkg install /tmp/luci-app-internet-detector_0.3.0-3_all.ipk
|
||||
rm /tmp/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.4-1_all.ipk
|
||||
rm /tmp/luci-app-internet-detector_0.4-1_all.ipk
|
||||
/etc/init.d/rpcd restart
|
||||
|
||||
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
|
||||
opkg install /tmp/luci-i18n-internet-detector-ru_0.3.0-3_all.ipk
|
||||
rm /tmp/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.4-1_all.ipk
|
||||
rm /tmp/luci-i18n-internet-detector-ru_0.4-1_all.ipk
|
||||
|
||||
**OpenWrt 19.07:**
|
||||
|
||||
@@ -45,20 +53,6 @@ i18n-ru:
|
||||
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
|
||||
|
||||
## Script for LED control:
|
||||
|
||||

|
||||
|
||||
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:
|
||||
|
||||

|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=internet-detector
|
||||
PKG_VERSION:=0.3.0
|
||||
PKG_RELEASE:=2
|
||||
PKG_VERSION:=0.4
|
||||
PKG_RELEASE:=1
|
||||
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||
|
||||
@@ -39,6 +39,8 @@ endef
|
||||
define Package/$(PKG_NAME)/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(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_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
|
||||
|
||||
@@ -1,18 +1,25 @@
|
||||
config main 'config'
|
||||
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_up_script '0'
|
||||
option enable_down_script '0'
|
||||
option enable_run_script '0'
|
||||
option interval_up '30'
|
||||
option interval_down '5'
|
||||
option ui_interval_up '6'
|
||||
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'
|
||||
|
||||
config module 'mod_led_control'
|
||||
option enabled '0'
|
||||
|
||||
@@ -35,11 +35,13 @@ local Config = {
|
||||
["connectionTimeout"] = 3,
|
||||
["UIConnectionTimeout"] = 1,
|
||||
["tcpPort"] = 53,
|
||||
["checkType"] = 0, -- 0: ping, 1: TCP
|
||||
["checkType"] = 0, -- 0: TCP, 1: ping
|
||||
["loggerLevel"] = "info",
|
||||
--["loggerCmd"] = "logger",
|
||||
["modules"] = {},
|
||||
}
|
||||
Config.configDir = "/etc/" .. Config.appName
|
||||
Config.modulesDir = "/usr/lib/" .. Config.appName
|
||||
Config.upScript = Config.configDir .. "/" .. "up-script"
|
||||
Config.downScript = Config.configDir .. "/" .. "down-script"
|
||||
Config.runScript = Config.configDir .. "/" .. "run-script"
|
||||
@@ -59,30 +61,28 @@ if not nixio then
|
||||
end
|
||||
|
||||
local uci = prequire("uci")
|
||||
if uci then
|
||||
|
||||
-- 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")
|
||||
if not uci then
|
||||
error("You need to install libuci-lua...")
|
||||
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 retValue = false
|
||||
local fh = io.open(filePath, "w")
|
||||
@@ -114,6 +114,28 @@ local function writeLogMessage(level, msg)
|
||||
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)
|
||||
if inetStat == nil then
|
||||
inetStat = ""
|
||||
@@ -164,7 +186,7 @@ local function tcpConnectToHost(host, port)
|
||||
end
|
||||
|
||||
local function checkHosts()
|
||||
local checkFunc = (Config.checkType == 1) and tcpConnectToHost or pingHost
|
||||
local checkFunc = (Config.checkType == 1) and pingHost or tcpConnectToHost
|
||||
local retCode = 1
|
||||
for k, v in ipairs(Config.parsedHosts) do
|
||||
for i = 1, Config.connectionAttempts do
|
||||
@@ -181,20 +203,20 @@ local function checkHosts()
|
||||
end
|
||||
|
||||
local function main()
|
||||
local last_status
|
||||
local current_status
|
||||
local lastStatus
|
||||
local currentStatus
|
||||
local interval = Config.intervalUp
|
||||
|
||||
while true do
|
||||
current_status = checkHosts()
|
||||
currentStatus = checkHosts()
|
||||
if not nixio.fs.access(Config.statusFile, "r") then
|
||||
writeValueToFile(Config.statusFile, current_status)
|
||||
writeValueToFile(Config.statusFile, currentStatus)
|
||||
end
|
||||
|
||||
if current_status == 0 then
|
||||
if currentStatus == 0 then
|
||||
interval = Config.intervalUp
|
||||
if last_status ~= nil and current_status ~= last_status then
|
||||
writeValueToFile(Config.statusFile, current_status)
|
||||
if lastStatus ~= nil and currentStatus ~= lastStatus then
|
||||
writeValueToFile(Config.statusFile, currentStatus)
|
||||
writeLogMessage("notice", "internet connected")
|
||||
if Config.enableUpScript == "1" then
|
||||
runExternalScript(Config.upScript)
|
||||
@@ -202,8 +224,8 @@ local function main()
|
||||
end
|
||||
else
|
||||
interval = Config.intervalDown
|
||||
if last_status ~= nil and current_status ~= last_status then
|
||||
writeValueToFile(Config.statusFile, current_status)
|
||||
if lastStatus ~= nil and currentStatus ~= lastStatus then
|
||||
writeValueToFile(Config.statusFile, currentStatus)
|
||||
writeLogMessage("notice", "internet disconnected")
|
||||
if Config.enableDownScript == "1" then
|
||||
runExternalScript(Config.downScript)
|
||||
@@ -211,11 +233,15 @@ local function main()
|
||||
end
|
||||
end
|
||||
|
||||
if Config.enableRunScript == "1" then
|
||||
runExternalScript(Config.runScript, current_status)
|
||||
for _, e in ipairs(Config.modules) do
|
||||
e:run(currentStatus, lastStatus)
|
||||
end
|
||||
|
||||
last_status = current_status
|
||||
if Config.enableRunScript == "1" then
|
||||
runExternalScript(Config.runScript, currentStatus)
|
||||
end
|
||||
|
||||
lastStatus = currentStatus
|
||||
nixio.nanosleep(interval)
|
||||
end
|
||||
end
|
||||
@@ -312,6 +338,19 @@ local function run()
|
||||
local pidValue = nixio.getpid()
|
||||
writeValueToFile(Config.pidFile, pidValue)
|
||||
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()
|
||||
end
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=0.3.0-3
|
||||
PKG_VERSION:=0.4-1
|
||||
LUCI_TITLE:=LuCI support for internet-detector
|
||||
LUCI_DEPENDS:=+internet-detector
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -17,6 +17,7 @@ return view.extend({
|
||||
upScriptPath : '/etc/internet-detector/up-script',
|
||||
downScriptPath : '/etc/internet-detector/down-script',
|
||||
runScriptPath : '/etc/internet-detector/run-script',
|
||||
ledsPath : '/sys/class/leds',
|
||||
pollInterval : L.env.pollinterval,
|
||||
appStatus : 'stoped',
|
||||
initStatus : null,
|
||||
@@ -31,6 +32,7 @@ return view.extend({
|
||||
uiCheckIntervalUp : null,
|
||||
uiCheckIntervalDown : null,
|
||||
currentAppMode : '0',
|
||||
leds : null,
|
||||
|
||||
callInitStatus: rpc.declare({
|
||||
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({
|
||||
ctx: null,
|
||||
|
||||
@@ -339,6 +355,7 @@ return view.extend({
|
||||
return Promise.all([
|
||||
fs.exec(this.execPath, [ 'status' ]),
|
||||
this.getInitStatus(),
|
||||
fs.list(this.ledsPath),
|
||||
uci.load('internet-detector'),
|
||||
]).catch(e => {
|
||||
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.initStatus = data[1];
|
||||
this.leds = data[2];
|
||||
this.currentAppMode = uci.get('internet-detector', 'config', 'mode');
|
||||
this.uiCheckIntervalUp = Number(uci.get('internet-detector', 'config', 'ui_interval_up'));
|
||||
this.uiCheckIntervalDown = Number(uci.get('internet-detector', 'config', 'ui_interval_down'));
|
||||
this.uiCheckIntervalUp = Number(uci.get('internet-detector', 'ui_config', 'interval_up'));
|
||||
this.uiCheckIntervalDown = Number(uci.get('internet-detector', 'ui_config', 'interval_down'));
|
||||
|
||||
let upScriptEditDialog = new this.fileEditDialog(
|
||||
this.upScriptPath,
|
||||
@@ -371,54 +389,57 @@ return view.extend({
|
||||
_("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'),
|
||||
_('Checking Internet availability.'));
|
||||
/* UCI sections */
|
||||
|
||||
s = m.section(form.NamedSection, 'config');
|
||||
s.anonymous = true;
|
||||
s.addremove = false;
|
||||
let s, o;
|
||||
|
||||
s.tab('main_settings', _('Main settings'));
|
||||
//// Main configuration
|
||||
|
||||
// service section
|
||||
o = s.taboption('main_settings', this.CBIBlockService, '_dummy_service');
|
||||
let mMain = new form.Map('internet-detector');
|
||||
s = mMain.section(form.NamedSection, 'config');
|
||||
|
||||
// service widget
|
||||
o = s.option(this.CBIBlockService, '_dummy_service');
|
||||
o.ctx = this;
|
||||
|
||||
// mode
|
||||
o = s.taboption('main_settings', form.ListValue,
|
||||
o = s.option(form.ListValue,
|
||||
'mode', _('Internet detector mode'));
|
||||
o.value('0', _('Disabled'));
|
||||
o.value('1', _('Web UI only'));
|
||||
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'),
|
||||
_('Web UI only: detector works only when the Web UI is open (UI detector)'),
|
||||
_('Service: detector always runs as a system service')
|
||||
);
|
||||
|
||||
// hosts
|
||||
o = s.taboption('main_settings', form.DynamicList,
|
||||
o = s.option(form.DynamicList,
|
||||
'hosts', _('Hosts'));
|
||||
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
|
||||
o = s.taboption('main_settings', form.ListValue,
|
||||
o = s.option(form.ListValue,
|
||||
'check_type', _('Check type'));
|
||||
o.description = _('Host availability check type');
|
||||
o.value(0, _('Ping host'));
|
||||
o.value(1, _('TCP port connection'));
|
||||
o.value(0, _('TCP port connection'));
|
||||
o.value(1, _('Ping host'));
|
||||
|
||||
// tcp_port
|
||||
o = s.taboption('main_settings', form.Value,
|
||||
o = s.option(form.Value,
|
||||
'tcp_port', _('TCP port'));
|
||||
o.description = _('Default port value for TCP connections');
|
||||
o.rmempty = false;
|
||||
o.datatype = "port";
|
||||
o.rmempty = false;
|
||||
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) {
|
||||
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')));
|
||||
}, this);
|
||||
|
||||
// ui_interval_up
|
||||
o = s.taboption('ui_detector_configuration', form.ListValue,
|
||||
'ui_interval_up', _('Alive interval'));
|
||||
// interval_up
|
||||
o = s.option(form.ListValue,
|
||||
'interval_up', _('Alive interval'));
|
||||
o.description = _('Hosts polling interval when the Internet is up');
|
||||
makeUIIntervalOptions(o);
|
||||
|
||||
// ui_interval_down
|
||||
o = s.taboption('ui_detector_configuration', form.ListValue,
|
||||
'ui_interval_down', _('Dead interval'));
|
||||
// interval_down
|
||||
o = s.option(form.ListValue,
|
||||
'interval_down', _('Dead interval'));
|
||||
o.description = _('Hosts polling interval when the Internet is down');
|
||||
makeUIIntervalOptions(o);
|
||||
|
||||
// ui_connection_attempts
|
||||
o = s.taboption('ui_detector_configuration', form.ListValue,
|
||||
'ui_connection_attempts', _('Connection attempts'));
|
||||
// connection_attempts
|
||||
o = s.option(form.ListValue,
|
||||
'connection_attempts', _('Connection attempts'));
|
||||
o.description = _('Maximum number of attempts to connect to each host');
|
||||
o.value(1);
|
||||
o.value(2);
|
||||
o.value(3);
|
||||
|
||||
// ui_connection_timeout
|
||||
o = s.taboption('ui_detector_configuration', form.ListValue,
|
||||
'ui_connection_timeout', _('Connection timeout'));
|
||||
// connection_timeout
|
||||
o = s.option(form.ListValue,
|
||||
'connection_timeout', _('Connection timeout'));
|
||||
o.description = _('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'));
|
||||
|
||||
s.tab('service_configuration', _('Service configuration'));
|
||||
|
||||
// enable_logger
|
||||
o = s.taboption('service_configuration', form.Flag,
|
||||
'enable_logger', _('Enable logging'));
|
||||
o.description = _('Write messages to the system log');
|
||||
o.rmempty = false;
|
||||
//// Service configuration
|
||||
|
||||
// enable_up_script
|
||||
o = s.taboption('service_configuration', 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.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';
|
||||
let mService = new form.Map('internet-detector');
|
||||
s = mService.section(form.NamedSection, 'service_config');
|
||||
|
||||
function makeIntervalOptions(list) {
|
||||
list.value(2, '2 ' + _('sec'));
|
||||
@@ -519,19 +499,19 @@ return view.extend({
|
||||
}
|
||||
|
||||
// interval_up
|
||||
o = s.taboption('service_configuration', form.ListValue,
|
||||
o = s.option(form.ListValue,
|
||||
'interval_up', _('Alive interval'));
|
||||
o.description = _('Hosts polling interval when the Internet is up');
|
||||
makeIntervalOptions(o);
|
||||
|
||||
// interval_down
|
||||
o = s.taboption('service_configuration', form.ListValue,
|
||||
o = s.option(form.ListValue,
|
||||
'interval_down', _('Dead interval'));
|
||||
o.description = _('Hosts polling interval when the Internet is down');
|
||||
makeIntervalOptions(o);
|
||||
|
||||
// connection_attempts
|
||||
o = s.taboption('service_configuration', form.ListValue,
|
||||
o = s.option(form.ListValue,
|
||||
'connection_attempts', _('Connection attempts'));
|
||||
o.description = _('Maximum number of attempts to connect to each host');
|
||||
o.value(1);
|
||||
@@ -541,7 +521,7 @@ return view.extend({
|
||||
o.value(5);
|
||||
|
||||
// connection_timeout
|
||||
o = s.taboption('service_configuration', form.ListValue,
|
||||
o = s.option( form.ListValue,
|
||||
'connection_timeout', _('Connection timeout'));
|
||||
o.description = _('Maximum timeout for waiting for a response from the host');
|
||||
o.value(1, "1 " + _('sec'));
|
||||
@@ -555,20 +535,153 @@ return view.extend({
|
||||
o.value(9, "9 " + _('sec'));
|
||||
o.value(10, "10 " + _('sec'));
|
||||
|
||||
if(this.currentAppMode !== '0') {
|
||||
poll.add(
|
||||
L.bind((this.currentAppMode === '2') ? this.servicePoll : this.uiPoll, this),
|
||||
this.pollInterval
|
||||
);
|
||||
// enable_logger
|
||||
o = s.option(form.Flag,
|
||||
'enable_logger', _('Enable logging'));
|
||||
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'));
|
||||
return mapPromise;
|
||||
|
||||
/* Rendering */
|
||||
|
||||
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) {
|
||||
return this.handleSave(ev).then(() => {
|
||||
return this.handleSave(ev).then(() => {
|
||||
ui.changes.apply(mode == '0');
|
||||
window.setTimeout(() => this.serviceRestart(), 3000);
|
||||
});
|
||||
|
||||
@@ -15,8 +15,8 @@ return baseclass.extend({
|
||||
'currentAppMode' in window
|
||||
)) {
|
||||
await uci.load('internet-detector').then(data => {
|
||||
window.uiCheckIntervalUp = Number(uci.get('internet-detector', 'config', 'ui_interval_up'));
|
||||
window.uiCheckIntervalDown = Number(uci.get('internet-detector', 'config', 'ui_interval_down'));
|
||||
window.uiCheckIntervalUp = Number(uci.get('internet-detector', 'ui_config', 'interval_up'));
|
||||
window.uiCheckIntervalDown = Number(uci.get('internet-detector', 'ui_config', 'interval_down'));
|
||||
window.currentAppMode = uci.get('internet-detector', 'config', 'mode');
|
||||
}).catch(e => {});
|
||||
};
|
||||
|
||||
@@ -24,12 +24,18 @@ msgstr "Тип проверки"
|
||||
msgid "Checking Internet availability."
|
||||
msgstr "Проверка доступности Интернет."
|
||||
|
||||
msgid "Collecting data..."
|
||||
msgstr "Сбор данных..."
|
||||
|
||||
msgid "Command failed"
|
||||
msgstr "Команда не выполнена"
|
||||
|
||||
msgid "Connected"
|
||||
msgstr "Подключен"
|
||||
|
||||
msgid "Connection attempts"
|
||||
msgstr "Попытки подключения"
|
||||
|
||||
msgid "Connection timeout"
|
||||
msgstr "Таймаут соединения"
|
||||
|
||||
@@ -55,7 +61,7 @@ msgid "Disconnected"
|
||||
msgstr "Отключен"
|
||||
|
||||
msgid "Dismiss"
|
||||
msgstr "Отмена"
|
||||
msgstr "Закрыть"
|
||||
|
||||
msgid "Edit"
|
||||
msgstr "Изменить"
|
||||
@@ -73,7 +79,7 @@ msgid "Enable down-script"
|
||||
msgstr "Включить down-script"
|
||||
|
||||
msgid "Enable logging"
|
||||
msgstr "Включить логирование"
|
||||
msgstr "Включить запись событий в лог"
|
||||
|
||||
msgid "Enable run-script"
|
||||
msgstr "Включить run-script"
|
||||
@@ -218,3 +224,18 @@ msgstr "сек"
|
||||
|
||||
msgid "up-script"
|
||||
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>..."
|
||||
|
||||
@@ -13,12 +13,18 @@ msgstr ""
|
||||
msgid "Checking Internet availability."
|
||||
msgstr ""
|
||||
|
||||
msgid "Collecting data..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Command failed"
|
||||
msgstr ""
|
||||
|
||||
msgid "Connected"
|
||||
msgstr ""
|
||||
|
||||
msgid "Connection attempts"
|
||||
msgstr ""
|
||||
|
||||
msgid "Connection timeout"
|
||||
msgstr ""
|
||||
|
||||
@@ -204,3 +210,18 @@ msgstr ""
|
||||
|
||||
msgid "up-script"
|
||||
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 ""
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"description": "Grant access to internet-detector procedures",
|
||||
"read": {
|
||||
"file": {
|
||||
"/sys/class/leds": [ "list" ],
|
||||
"/etc/internet-detector/up-script": [ "read" ],
|
||||
"/etc/internet-detector/down-script": [ "read" ],
|
||||
"/etc/internet-detector/run-script": [ "read" ],
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 199 KiB After Width: | Height: | Size: 155 KiB |
Reference in New Issue
Block a user