diff --git a/README.md b/README.md index 74cbb7b..77caad8 100644 --- a/README.md +++ b/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. +![](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 **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: - -![](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: ![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/01.jpg) diff --git a/internet-detector/Makefile b/internet-detector/Makefile index 66eb264..c44c781 100644 --- a/internet-detector/Makefile +++ b/internet-detector/Makefile @@ -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 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 diff --git a/internet-detector/files/etc/config/internet-detector b/internet-detector/files/etc/config/internet-detector index c174361..3e217ad 100644 --- a/internet-detector/files/etc/config/internet-detector +++ b/internet-detector/files/etc/config/internet-detector @@ -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' diff --git a/internet-detector/files/usr/bin/internet-detector b/internet-detector/files/usr/bin/internet-detector index 349ca7f..6fa2a3d 100755 --- a/internet-detector/files/usr/bin/internet-detector +++ b/internet-detector/files/usr/bin/internet-detector @@ -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 diff --git a/internet-detector/files/usr/lib/internet-detector/mod_led_control.lua b/internet-detector/files/usr/lib/internet-detector/mod_led_control.lua new file mode 100644 index 0000000..30d31df --- /dev/null +++ b/internet-detector/files/usr/lib/internet-detector/mod_led_control.lua @@ -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 diff --git a/led/etc/internet-detector/run-script b/led/etc/internet-detector/run-script deleted file mode 100755 index 9a1e874..0000000 --- a/led/etc/internet-detector/run-script +++ /dev/null @@ -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 diff --git a/led/usr/bin/internet-detector-led.sh b/led/usr/bin/internet-detector-led.sh deleted file mode 100755 index 237ec14..0000000 --- a/led/usr/bin/internet-detector-led.sh +++ /dev/null @@ -1,63 +0,0 @@ -#/bin/sh - -# -# Usage: internet-detector-led.sh on|off|state|list [|] -# -# 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 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 [|]" >&2 - exit 1 -;; -esac - -exit 0; diff --git a/luci-app-internet-detector/Makefile b/luci-app-internet-detector/Makefile index 24f8cbd..cc62faa 100644 --- a/luci-app-internet-detector/Makefile +++ b/luci-app-internet-detector/Makefile @@ -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 diff --git a/luci-app-internet-detector/htdocs/luci-static/resources/view/internet-detector.js b/luci-app-internet-detector/htdocs/luci-static/resources/view/internet-detector.js index 7667844..cec001f 100644 --- a/luci-app-internet-detector/htdocs/luci-static/resources/view/internet-detector.js +++ b/luci-app-internet-detector/htdocs/luci-static/resources/view/internet-detector.js @@ -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;
%s;
%s;'.format( + o.description = '%s;
%s;
%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 = _('LED control') + ':'; + + if(this.leds && this.leds.length > 0) { + + // enabled + o = s.option(form.Flag, 'enabled', + _('Enable LED control')); + o.rmempty = false; + o.description = _('LED is on when Internet is available.'); + + // led_name + o = s.option(form.ListValue, 'led_name', + _('LED 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 = '
' + + _('No LEDs available...') + + '
'; }; - 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); }); diff --git a/luci-app-internet-detector/htdocs/luci-static/resources/view/status/include/00_internet.js b/luci-app-internet-detector/htdocs/luci-static/resources/view/status/include/00_internet.js index a4ecfee..fd995fa 100644 --- a/luci-app-internet-detector/htdocs/luci-static/resources/view/status/include/00_internet.js +++ b/luci-app-internet-detector/htdocs/luci-static/resources/view/status/include/00_internet.js @@ -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 => {}); }; diff --git a/luci-app-internet-detector/po/ru/internet-detector.po b/luci-app-internet-detector/po/ru/internet-detector.po index 0d1a469..033f736 100644 --- a/luci-app-internet-detector/po/ru/internet-detector.po +++ b/luci-app-internet-detector/po/ru/internet-detector.po @@ -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 "LED control" +msgstr "Управление LED" + +msgid "LED is on when Internet is available." +msgstr "LED включен если Интернет доступен." + +msgid "LED Name" +msgstr "Имя LED" + +msgid "Enable LED control" +msgstr "Включить управление LED" + +msgid "No LEDs available..." +msgstr "Нет доступных LED..." diff --git a/luci-app-internet-detector/po/templates/internet-detector.pot b/luci-app-internet-detector/po/templates/internet-detector.pot index ad584b7..f818fa2 100644 --- a/luci-app-internet-detector/po/templates/internet-detector.pot +++ b/luci-app-internet-detector/po/templates/internet-detector.pot @@ -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 "LED control" +msgstr "" + +msgid "LED is on when Internet is available." +msgstr "" + +msgid "LED Name" +msgstr "" + +msgid "Enable LED control" +msgstr "" + +msgid "No LEDs available..." +msgstr "" diff --git a/luci-app-internet-detector/root/usr/share/rpcd/acl.d/luci-app-internet-detector.json b/luci-app-internet-detector/root/usr/share/rpcd/acl.d/luci-app-internet-detector.json index cf1da28..4f53d74 100644 --- a/luci-app-internet-detector/root/usr/share/rpcd/acl.d/luci-app-internet-detector.json +++ b/luci-app-internet-detector/root/usr/share/rpcd/acl.d/luci-app-internet-detector.json @@ -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" ], diff --git a/screenshots/03.jpg b/screenshots/03.jpg index 312101e..a76c483 100644 Binary files a/screenshots/03.jpg and b/screenshots/03.jpg differ