mod_led_control: multi LED

This commit is contained in:
gSpot
2025-02-18 16:12:41 +03:00
parent dd46273f24
commit 6c19812db5
10 changed files with 196 additions and 165 deletions

View File

@@ -15,22 +15,22 @@ Internet-detector is an application for checking the availability of the Interne
## Installation notes (OpenWrt >= 21.02) ## Installation notes (OpenWrt >= 21.02)
opkg update opkg update
wget --no-check-certificate -O /tmp/internet-detector_1.4.0-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector_1.4.0-r1_all.ipk wget --no-check-certificate -O /tmp/internet-detector_1.4.1-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector_1.4.1-r1_all.ipk
opkg install /tmp/internet-detector_1.4.0-r1_all.ipk opkg install /tmp/internet-detector_1.4.1-r1_all.ipk
rm /tmp/internet-detector_1.4.0-r1_all.ipk rm /tmp/internet-detector_1.4.1-r1_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_1.4.0-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-app-internet-detector_1.4.0-r1_all.ipk wget --no-check-certificate -O /tmp/luci-app-internet-detector_1.4.1-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-app-internet-detector_1.4.1-r1_all.ipk
opkg install /tmp/luci-app-internet-detector_1.4.0-r1_all.ipk opkg install /tmp/luci-app-internet-detector_1.4.1-r1_all.ipk
rm /tmp/luci-app-internet-detector_1.4.0-r1_all.ipk rm /tmp/luci-app-internet-detector_1.4.1-r1_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_1.4.0-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-i18n-internet-detector-ru_1.4.0-r1_all.ipk wget --no-check-certificate -O /tmp/luci-i18n-internet-detector-ru_1.4.1-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-i18n-internet-detector-ru_1.4.1-r1_all.ipk
opkg install /tmp/luci-i18n-internet-detector-ru_1.4.0-r1_all.ipk opkg install /tmp/luci-i18n-internet-detector-ru_1.4.1-r1_all.ipk
rm /tmp/luci-i18n-internet-detector-ru_1.4.0-r1_all.ipk rm /tmp/luci-i18n-internet-detector-ru_1.4.1-r1_all.ipk
## Screenshots: ## Screenshots:
@@ -42,9 +42,9 @@ i18n-ru:
**Dependences:** modemmanager. **Dependences:** modemmanager.
wget --no-check-certificate -O /tmp/internet-detector-mod-modem-restart_1.4.0-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector-mod-modem-restart_1.4.0-r1_all.ipk wget --no-check-certificate -O /tmp/internet-detector-mod-modem-restart_1.4.1-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector-mod-modem-restart_1.4.1-r1_all.ipk
opkg install /tmp/internet-detector-mod-modem-restart_1.4.0-r1_all.ipk opkg install /tmp/internet-detector-mod-modem-restart_1.4.1-r1_all.ipk
rm /tmp/internet-detector-mod-modem-restart_1.4.0-r1_all.ipk rm /tmp/internet-detector-mod-modem-restart_1.4.1-r1_all.ipk
/etc/init.d/internet-detector restart /etc/init.d/internet-detector restart
![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/04.jpg) ![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/04.jpg)
@@ -53,9 +53,9 @@ i18n-ru:
**Dependences:** mailsend. **Dependences:** mailsend.
wget --no-check-certificate -O /tmp/internet-detector-mod-email_1.4.0-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector-mod-email_1.4.0-r1_all.ipk wget --no-check-certificate -O /tmp/internet-detector-mod-email_1.4.1-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector-mod-email_1.4.1-r1_all.ipk
opkg install /tmp/internet-detector-mod-email_1.4.0-r1_all.ipk opkg install /tmp/internet-detector-mod-email_1.4.1-r1_all.ipk
rm /tmp/internet-detector-mod-email_1.4.0-r1_all.ipk rm /tmp/internet-detector-mod-email_1.4.1-r1_all.ipk
/etc/init.d/internet-detector restart /etc/init.d/internet-detector restart
![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/05.jpg) ![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/05.jpg)

View File

@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=internet-detector-mod-email PKG_NAME:=internet-detector-mod-email
PKG_VERSION:=1.4.0 PKG_VERSION:=1.4.1
PKG_RELEASE:=1 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>

View File

@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=internet-detector-mod-modem-restart PKG_NAME:=internet-detector-mod-modem-restart
PKG_VERSION:=1.4.0 PKG_VERSION:=1.4.1
PKG_RELEASE:=1 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>

View File

@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=internet-detector PKG_NAME:=internet-detector
PKG_VERSION:=1.4.0 PKG_VERSION:=1.4.1
PKG_RELEASE:=1 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>

View File

@@ -13,6 +13,7 @@ config instance 'internet'
option interval_down '5' option interval_down '5'
option connection_attempts '2' option connection_attempts '2'
option connection_timeout '2' option connection_timeout '2'
option mod_led_control_enabled '0'
option mod_reboot_enabled '0' option mod_reboot_enabled '0'
option mod_reboot_dead_period '3600' option mod_reboot_dead_period '3600'
option mod_reboot_force_reboot_delay '300' option mod_reboot_force_reboot_delay '300'

View File

@@ -3,25 +3,21 @@ local unistd = require("posix.unistd")
local dirent = require("posix.dirent") local dirent = require("posix.dirent")
local Module = { local Module = {
name = "mod_led_control", name = "mod_led_control",
runPrio = 10, runPrio = 10,
config = {}, config = {},
syslog = function(level, msg) return true end, syslog = function(level, msg) return true end,
writeValue = function(filePath, str) return false end, writeValue = function(filePath, str) return false end,
readValue = function(filePath) return nil end, readValue = function(filePath) return nil end,
runInterval = 5, runInterval = 5,
sysLedsDir = "/sys/class/leds", sysLedsDir = "/sys/class/leds",
ledName = nil, ledsPerInstance = 3,
ledAction1 = 2, -- 1: off, 2: on, 3: blink ledAction1Default = 1, -- 1: off, 2: on, 3: blink
ledAction2 = 1, -- 1: off, 2: on, 3: blink ledAction2Default = 1,
status = nil, status = nil,
_enabled = false, _enabled = false,
_ledDir = nil, _leds = {},
_ledMaxBrightnessFile = nil, _counter = 0,
_ledBrightnessFile = nil,
_ledMaxBrightness = nil,
_ledTriggerFile = nil,
_counter = 0,
} }
function Module:resetLeds() function Module:resetLeds()
@@ -37,101 +33,121 @@ function Module:resetLeds()
end end
end end
function Module:init(t) function Module:setLedAttrs(t)
if not t.led_name then t.ledDir = string.format("%s/%s", self.sysLedsDir, t.ledName)
return t.ledMaxBrightnessFile = string.format("%s/max_brightness", t.ledDir)
else t.ledBrightnessFile = string.format("%s/brightness", t.ledDir)
self.ledName = t.led_name t.ledMaxBrightness = self.readValue(t.ledMaxBrightnessFile) or 1
end t.ledTriggerFile = string.format("%s/trigger", t.ledDir)
if t.led_action_1 ~= nil then end
self.ledAction1 = tonumber(t.led_action_1)
end
if t.led_action_2 ~= nil then
self.ledAction2 = tonumber(t.led_action_2)
end
self._ledDir = string.format("%s/%s", self.sysLedsDir, self.ledName)
self._ledMaxBrightnessFile = string.format("%s/max_brightness", self._ledDir)
self._ledBrightnessFile = string.format("%s/brightness", self._ledDir)
self._ledMaxBrightness = self.readValue(self._ledMaxBrightnessFile) or 1
self._ledTriggerFile = string.format("%s/trigger", self._ledDir)
if (not unistd.access(self._ledDir, "r") or function Module:checkLed(t)
not unistd.access(self._ledBrightnessFile, "rw") or return (unistd.access(t.ledDir, "r") and
not unistd.access(self._ledTriggerFile, "rw")) then unistd.access(t.ledBrightnessFile, "rw") and
self._enabled = false unistd.access(t.ledTriggerFile, "rw"))
self.syslog("warning", string.format( end
"%s: LED '%s' is not available", self.name, self.ledName))
else function Module:init(t)
for i = 1, self.ledsPerInstance do
self._leds[i] = {}
end
if t.led1_name then
self._enabled = true self._enabled = true
-- Reset all LEDs -- Reset all LEDs
--self:resetLeds() --self:resetLeds()
else
return
end
for i, l in ipairs(self._leds) do
if t["led" .. i .. "_name"] ~= nil then
l.ledName = t["led" .. i .. "_name"]
l.ledAction1 = tonumber(t["led" .. i .. "_action_1"]) or self.ledAction1Default
l.ledAction2 = tonumber(t["led" .. i .. "_action_2"]) or self.ledAction2Default
self:setLedAttrs(l)
l.enabled = true
else
l.enabled = false
end
if l.enabled and not self:checkLed(l) then
self._enabled = false
self.syslog("err", string.format(
"%s: module disabled. LED '%s' is not available", self.name, l.ledName))
end
end end
end end
function Module:SetTriggerTimer() function Module:SetTriggerTimer(t)
self.writeValue(self._ledTriggerFile, "timer") self.writeValue(t.ledTriggerFile, "timer")
end end
function Module:SetTriggerNone() function Module:SetTriggerNone(t)
self.writeValue(self._ledTriggerFile, "none") self.writeValue(t.ledTriggerFile, "none")
end end
function Module:getCurrentTrigger() function Module:getCurrentTrigger(t)
local trigger = self.readValue(self._ledTriggerFile) local trigger = self.readValue(t.ledTriggerFile)
if trigger and trigger:match("%[timer%]") then if trigger and trigger:match("%[timer%]") then
return 1 return true
end end
end end
function Module:on() function Module:on(t)
self:SetTriggerNone() self:SetTriggerNone(t)
self.writeValue(self._ledBrightnessFile, self._ledMaxBrightness) self.writeValue(t.ledBrightnessFile, t.ledMaxBrightness)
end end
function Module:off() function Module:off(t)
self:SetTriggerNone() self:SetTriggerNone(t)
self.writeValue(self._ledBrightnessFile, 0) self.writeValue(t.ledBrightnessFile, 0)
end end
function Module:getCurrentState() function Module:getCurrentState(t)
local state = self.readValue(self._ledBrightnessFile) local state = self.readValue(t.ledBrightnessFile)
if state and tonumber(state) > 0 then if state and tonumber(state) > 0 then
return tonumber(state) return tonumber(state)
end end
end end
function Module:ledRunFunc(t, currentStatus)
if currentStatus == 0 then
if t.ledAction1 == 1 then
if self:getCurrentState(t) or self:getCurrentTrigger(t) then
self:off(t)
end
elseif t.ledAction1 == 2 then
if not self:getCurrentState(t) or self:getCurrentTrigger(t) then
self:on(t)
end
elseif t.ledAction1 == 3 then
if not self:getCurrentTrigger(t) then
self:SetTriggerTimer(t)
end
end
else
if t.ledAction2 == 1 then
if self:getCurrentState(t) or self:getCurrentTrigger(t) then
self:off(t)
end
elseif t.ledAction2 == 2 then
if not self:getCurrentState(t) or self:getCurrentTrigger(t) then
self:on(t)
end
elseif t.ledAction2 == 3 then
if not self:getCurrentTrigger(t) then
self:SetTriggerTimer(t)
end
end
end
end
function Module:run(currentStatus, lastStatus, timeDiff, timeNow) function Module:run(currentStatus, lastStatus, timeDiff, timeNow)
if not self._enabled then if not self._enabled then
return return
end end
if self._counter == 0 or self._counter >= self.runInterval or currentStatus ~= lastStatus then if self._counter == 0 or self._counter >= self.runInterval or currentStatus ~= lastStatus then
if currentStatus == 0 then for _, t in ipairs(self._leds) do
if self.ledAction1 == 1 then if t.enabled then
if self:getCurrentState() or self:getCurrentTrigger() then self:ledRunFunc(t, currentStatus)
self:off()
end
elseif self.ledAction1 == 2 then
if not self:getCurrentState() or self:getCurrentTrigger() then
self:on()
end
elseif self.ledAction1 == 3 then
if not self:getCurrentTrigger() then
self:SetTriggerTimer()
end
end
else
if self.ledAction2 == 1 then
if self:getCurrentState() or self:getCurrentTrigger() then
self:off()
end
elseif self.ledAction2 == 2 then
if not self:getCurrentState() or self:getCurrentTrigger() then
self:on()
end
elseif self.ledAction2 == 3 then
if not self:getCurrentTrigger() then
self:SetTriggerTimer()
end
end end
end end
self._counter = 0 self._counter = 0

View File

@@ -324,7 +324,7 @@ function Module:resolveIP()
res = table.concat(retTable, ", ") res = table.concat(retTable, ", ")
end end
else else
self.syslog("err", string.format( self.syslog("warning", string.format(
"%s: DNS error when requesting an IP address", self.name)) "%s: DNS error when requesting an IP address", self.name))
end end

View File

@@ -3,17 +3,17 @@ local stdlib = require("posix.stdlib")
local unistd = require("posix.unistd") local unistd = require("posix.unistd")
local Module = { local Module = {
name = "mod_regular_script", name = "mod_regular_script",
runPrio = 90, runPrio = 90,
config = {}, config = {},
syslog = function(level, msg) return true end, syslog = function(level, msg) return true end,
writeValue = function(filePath, str) return false end, writeValue = function(filePath, str) return false end,
readValue = function(filePath) return nil end, readValue = function(filePath) return nil end,
inetState = 2, -- 0: connected, 1: disconnected, 2: both inetState = 2, -- 0: connected, 1: disconnected, 2: both
interval = 3600, runInterval = 3600,
script = "", script = "",
status = nil, status = nil,
_nextTime = nil, _nextTime = nil,
} }
function Module:runExternalScript(scriptPath, currentStatus) function Module:runExternalScript(scriptPath, currentStatus)
@@ -28,7 +28,7 @@ function Module:init(t)
self.inetState = tonumber(t.inet_state) self.inetState = tonumber(t.inet_state)
end end
if t.interval ~= nil then if t.interval ~= nil then
self.interval = tonumber(t.interval) self.runInterval = tonumber(t.interval)
end end
if self.config.configDir then if self.config.configDir then
self.script = string.format( self.script = string.format(
@@ -38,17 +38,17 @@ end
function Module:run(currentStatus, lastStatus, timeDiff, timeNow) function Module:run(currentStatus, lastStatus, timeDiff, timeNow)
if not self._nextTime then if not self._nextTime then
if timeNow < self.interval then if timeNow < self.runInterval then
self._nextTime = self.interval self._nextTime = self.runInterval
else else
self._nextTime = timeNow - (timeNow % self.interval) + self.interval self._nextTime = timeNow - (timeNow % self.runInterval) + self.runInterval
end end
end end
if timeNow >= self._nextTime then if timeNow >= self._nextTime then
if self.inetState == 2 or (self.inetState == 0 and currentStatus == 0) or (self.inetState == 1 and currentStatus == 1) then if self.inetState == 2 or (self.inetState == 0 and currentStatus == 0) or (self.inetState == 1 and currentStatus == 1) then
self:runExternalScript(self.script, currentStatus) self:runExternalScript(self.script, currentStatus)
end end
self._nextTime = self._nextTime + self.interval self._nextTime = self._nextTime + self.runInterval
end end
end end

View File

@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-internet-detector PKG_NAME:=luci-app-internet-detector
PKG_VERSION:=1.4.0 PKG_VERSION:=1.4.1
PKG_RELEASE:=1 PKG_RELEASE:=1
LUCI_TITLE:=LuCI support for internet-detector LUCI_TITLE:=LuCI support for internet-detector
LUCI_DEPENDS:=+internet-detector LUCI_DEPENDS:=+internet-detector

View File

@@ -134,23 +134,24 @@ var Timefield = ui.Textfield.extend({
}); });
return view.extend({ return view.extend({
appName : 'internet-detector', appName : 'internet-detector',
configDir : '/etc/internet-detector', configDir : '/etc/internet-detector',
ledsPath : '/sys/class/leds', pollInterval : L.env.pollinterval,
pollInterval : L.env.pollinterval, appStatus : 'stoped',
appStatus : 'stoped', initStatus : null,
initStatus : null, inetStatus : null,
inetStatus : null, inetStatusArea : E('div', { 'class': 'cbi-value-field', 'id': 'inetStatusArea' }),
inetStatusArea : E('div', { 'class': 'cbi-value-field', 'id': 'inetStatusArea' }), serviceStatusLabel : E('em', { 'id': 'serviceStatusLabel' }),
serviceStatusLabel : E('em', { 'id': 'serviceStatusLabel' }), initButton : null,
initButton : null, currentAppMode : '0',
currentAppMode : '0', defaultHosts : [ '8.8.8.8', '1.1.1.1' ],
defaultHosts : [ '8.8.8.8', '1.1.1.1' ], ledsPath : '/sys/class/leds',
leds : [], ledsPerInstance : 3,
mm : false, leds : [],
mmInit : false, mm : false,
email : false, mmInit : false,
emailExec : false, email : false,
emailExec : false,
callInitStatus: rpc.declare({ callInitStatus: rpc.declare({
object: 'luci', object: 'luci',
@@ -511,9 +512,9 @@ return view.extend({
if(!data) { if(!data) {
return; return;
}; };
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.leds = data[2];
if(data[3]) { if(data[3]) {
if(data[3].mm_mod) { if(data[3].mm_mod) {
this.mm = true; this.mm = true;
@@ -566,7 +567,6 @@ return view.extend({
/* Main settings */ /* Main settings */
// mode // mode
let mode = s.option(form.ListValue, 'mode', let mode = s.option(form.ListValue, 'mode',
_('Internet detector mode')); _('Internet detector mode'));
mode.value('0', _('Disabled')); mode.value('0', _('Disabled'));
@@ -579,6 +579,7 @@ return view.extend({
); );
mode.default = '0'; mode.default = '0';
/* Service instances configuration */ /* Service instances configuration */
if(this.currentAppMode !== '2') { if(this.currentAppMode !== '2') {
@@ -767,32 +768,45 @@ return view.extend({
o.rmempty = false; o.rmempty = false;
o.modalonly = true; o.modalonly = true;
// led_name o = s.taboption('led_control', form.SectionValue, s.section, form.NamedSection,
o = s.taboption('led_control', form.ListValue, 'mod_led_control_led_name', s.section);
_('<abbr title="Light Emitting Diode">LED</abbr> Name'));
o.depends({ mod_led_control_enabled: '1' }); o.depends({ mod_led_control_enabled: '1' });
o.modalonly = true; ss = o.subsection;
this.leds.forEach(e => o.value(e.name));
// led_action_1 for(let i = 1; i <= this.ledsPerInstance; i++) {
o = s.taboption('led_control', form.ListValue, 'mod_led_control_led_action_1', ss.tab('led' + i + '_tab', _('LED') + ' ' + i);
_('Action when connected'));
o.depends({ mod_led_control_enabled: '1' });
o.modalonly = true;
o.value(1, _('Off'));
o.value(2, _('On'));
o.value(3, _('Blink'));
o.default = '2';
// led_action_2 // led_name
o = s.taboption('led_control', form.ListValue, 'mod_led_control_led_action_2', o = ss.taboption('led' + i + '_tab', form.ListValue, 'mod_led_control_led' + i + '_name',
_('Action when disconnected')); _('<abbr title="Light Emitting Diode">LED</abbr> Name'));
o.depends({ mod_led_control_enabled: '1' }); o.depends({ mod_led_control_enabled: '1' });
o.modalonly = true; o.modalonly = true;
o.value(1, _('Off')); if(i > 1) {
o.value(2, _('On')); o.rmempty = true;
o.value(3, _('Blink')); o.optional = true;
o.default = '1'; };
this.leds.forEach(e => o.value(e.name));
// led_action_1
o = ss.taboption('led' + i + '_tab', form.ListValue, 'mod_led_control_led' + i + '_action_1',
_('Action when connected'));
o.depends({ ['mod_led_control_led' + i + '_name']: /.+/ });
o.modalonly = true;
o.value(1, _('Off'));
o.value(2, _('On'));
o.value(3, _('Blink'));
o.default = '2';
// led_action_2
o = ss.taboption('led' + i + '_tab', form.ListValue, 'mod_led_control_led' + i + '_action_2',
_('Action when disconnected'));
o.depends({ ['mod_led_control_led' + i + '_name']: /.+/ });
o.modalonly = true;
o.value(1, _('Off'));
o.value(2, _('On'));
o.value(3, _('Blink'));
o.default = '1';
};
} else { } else {
o = s.taboption('led_control', form.DummyValue, '_dummy'); o = s.taboption('led_control', form.DummyValue, '_dummy');
o.rawhtml = true; o.rawhtml = true;