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)
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
opkg install /tmp/internet-detector_1.4.0-r1_all.ipk
rm /tmp/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.1-r1_all.ipk
rm /tmp/internet-detector_1.4.1-r1_all.ipk
/etc/init.d/internet-detector start
/etc/init.d/internet-detector enable
wget --no-check-certificate -O /tmp/luci-app-internet-detector_1.4.0-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-app-internet-detector_1.4.0-r1_all.ipk
opkg install /tmp/luci-app-internet-detector_1.4.0-r1_all.ipk
rm /tmp/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.1-r1_all.ipk
rm /tmp/luci-app-internet-detector_1.4.1-r1_all.ipk
/etc/init.d/rpcd restart
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
opkg install /tmp/luci-i18n-internet-detector-ru_1.4.0-r1_all.ipk
rm /tmp/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.1-r1_all.ipk
rm /tmp/luci-i18n-internet-detector-ru_1.4.1-r1_all.ipk
## Screenshots:
@@ -42,9 +42,9 @@ i18n-ru:
**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
opkg install /tmp/internet-detector-mod-modem-restart_1.4.0-r1_all.ipk
rm /tmp/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.1-r1_all.ipk
rm /tmp/internet-detector-mod-modem-restart_1.4.1-r1_all.ipk
/etc/init.d/internet-detector restart
![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/04.jpg)
@@ -53,9 +53,9 @@ i18n-ru:
**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
opkg install /tmp/internet-detector-mod-email_1.4.0-r1_all.ipk
rm /tmp/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.1-r1_all.ipk
rm /tmp/internet-detector-mod-email_1.4.1-r1_all.ipk
/etc/init.d/internet-detector restart
![](https://github.com/gSpotx2f/luci-app-internet-detector/blob/master/screenshots/05.jpg)

View File

@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=internet-detector-mod-email
PKG_VERSION:=1.4.0
PKG_VERSION:=1.4.1
PKG_RELEASE:=1
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>

View File

@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=internet-detector-mod-modem-restart
PKG_VERSION:=1.4.0
PKG_VERSION:=1.4.1
PKG_RELEASE:=1
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>

View File

@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=internet-detector
PKG_VERSION:=1.4.0
PKG_VERSION:=1.4.1
PKG_RELEASE:=1
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 connection_attempts '2'
option connection_timeout '2'
option mod_led_control_enabled '0'
option mod_reboot_enabled '0'
option mod_reboot_dead_period '3600'
option mod_reboot_force_reboot_delay '300'

View File

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

View File

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

View File

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

View File

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

View File

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