Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

luci-app-timewol: Script improvement and multilingualization #425

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions applications/luci-app-timewol/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (C) 2016 Openwrt.org
# Copyright (C) 2024 iv7777 <[email protected]>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
Expand All @@ -7,8 +8,8 @@ include $(TOPDIR)/rules.mk

LUCI_TITLE:=LuCI support for Timewol
LUCI_PKGARCH:=all
PKG_VERSION:=1.0
PKG_RELEASE:=3-20190309
PKG_VERSION:=1.1
PKG_RELEASE:=1-20240520

include ../../luci.mk

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ function index()
if not nixio.fs.access("/etc/config/timewol") then return end

entry({"admin", "control"}, firstchild(), "Control", 44).dependent = false
local page = entry({"admin", "control", "timewol"}, cbi("timewol"), _("定时唤醒"))
local page = entry({"admin", "control", "timewol"}, cbi("timewol"), _("Timed WOL"))
page.order = 95
page.dependent = true
page.acl_depends = { "luci-app-timewol" }
Expand Down
123 changes: 86 additions & 37 deletions applications/luci-app-timewol/luasrc/model/cbi/timewol.lua
Original file line number Diff line number Diff line change
@@ -1,37 +1,86 @@
local i = require "luci.sys"
local t, e, o
t = Map("timewol", translate("定时网络唤醒"),
translate("定时唤醒你的局域网设备"))
t.template = "timewol/index"
e = t:section(TypedSection, "basic", translate("Running Status"))
e.anonymous = true
o = e:option(DummyValue, "timewol_status", translate("当前状态"))
o.template = "timewol/timewol"
o.value = translate("Collecting data...")
e = t:section(TypedSection, "basic", translate("基本设置"))
e.anonymous = true
o = e:option(Flag, "enable", translate("开启"))
o.rmempty = false
e = t:section(TypedSection, "macclient", translate("客户端设置"))
e.template = "cbi/tblsection"
e.anonymous = true
e.addremove = true
nolimit_mac = e:option(Value, "macaddr", translate("客户端MAC"))
nolimit_mac.rmempty = false
i.net.mac_hints(function(e, t) nolimit_mac:value(e, "%s (%s)" % {e, t}) end)
nolimit_eth = e:option(Value, "maceth", translate("网络接口"))
nolimit_eth.rmempty = false
for t, e in ipairs(i.net.devices()) do if e ~= "lo" then nolimit_eth:value(e) end end
a = e:option(Value, "minute", translate("分钟"))
a.optional = false
a = e:option(Value, "hour", translate("小时"))
a.optional = false
a = e:option(Value, "day", translate("日"))
a.optional = false
a = e:option(Value, "month", translate("月"))
a.optional = false
a = e:option(Value, "weeks", translate("星期"))
a.optional = false
local e = luci.http.formvalue("cbi.apply")
if e then io.popen("/etc/init.d/timewol restart") end
return t
local sys = require "luci.sys"

-- Create the main map object
local map = Map("timewol", translate("Timed Wake on LAN"),
translate("Wake up your local area network devices on schedule"))
map.template = "timewol/index"

-- Running Status Section
local status_section = map:section(TypedSection, "basic", translate("Running Status"))
status_section.anonymous = true

local status = status_section:option(DummyValue, "timewol_status", translate("Current Status"))
status.template = "timewol/timewol"
status.value = translate("Collecting data...")

-- Basic Settings Section
local basic_section = map:section(TypedSection, "basic", translate("Basic Settings"))
basic_section.anonymous = true

local enable = basic_section:option(Flag, "enable", translate("Enable"))
enable.rmempty = false

-- Client Settings Section
local client_section = map:section(TypedSection, "macclient", translate("Client Settings"))
client_section.template = "cbi/tblsection"
client_section.anonymous = true
client_section.addremove = true

-- Client MAC Address
local mac_addr = client_section:option(Value, "macaddr", translate("Client MAC"))
mac_addr.rmempty = false
sys.net.mac_hints(function(mac, hint)
mac_addr:value(mac, string.format("%s (%s)", mac, hint))
end)

-- Network Interface
local net_iface = client_section:option(Value, "maceth", translate("Network Interface"))
net_iface.rmempty = false
net_iface.default = "br-lan"
for _, device in ipairs(sys.net.devices()) do
if device ~= "lo" then
net_iface:value(device)
end
end

-- Function to validate cron field values
local function validate_cron_field(option_name, value, min, max, default)
if value == "" then
return default
elseif value == "*" then
return value
end
local num = tonumber(value)
if num and num >= min and num <= max then
return value
else
return nil, translatef("Invalid value for %s: %s. Must be between %d and %d or '*'", option_name, value, min, max)
end
end

-- Scheduling Options with Default Values and Range Checks
local schedule_options = {
{ "minute", translate("Minute"), 0, 59, "0" },
{ "hour", translate("Hour"), 0, 23, "0" },
{ "day", translate("Day"), 1, 31, "*" },
{ "month", translate("Month"), 1, 12, "*" },
{ "weeks", translate("Week"), 0, 6, "*" } -- 0 for Sunday, 6 for Saturday
}

for _, opt in ipairs(schedule_options) do
local field = client_section:option(Value, opt[1], opt[2])
field.default = opt[5] or opt[4] -- Use default value if present, otherwise use maximum value
field.optional = false
field.validate = function(self, value)
return validate_cron_field(opt[2], value, opt[3], opt[4], field.default)
end
end

-- Apply the configuration changes
map.apply_on_parse = true
function map.on_apply(self)
sys.exec("/etc/init.d/timewol restart")
end

return map

52 changes: 52 additions & 0 deletions applications/luci-app-timewol/po/zh_Hans/timewol.po
Original file line number Diff line number Diff line change
@@ -1,2 +1,54 @@
msgid "Control"
msgstr "管控"

msgid "Timed WOL"
msgstr "定时网络唤醒"

msgid "Timed Wake on LAN"
msgstr "定时网络唤醒"

msgid "Wake up your local area network devices on schedule"
msgstr "定时唤醒你的局域网设备"

msgid "Timed WOL"
msgstr "定时网络唤醒"

msgid "Running Status"
msgstr "运行状态"

msgid "Current Status"
msgstr "当前状态"

msgid "Basic Settings"
msgstr "基本设置"

msgid "Enable"
msgstr "开启"

msgid "Client Settings"
msgstr "客户端设置"

msgid "Client MAC"
msgstr "客户端MAC"

msgid "Network Interface"
msgstr "网络接口"

msgid "Minute"
msgstr "分钟"

msgid "Hour"
msgstr "小时"

msgid "Day"
msgstr "日"

msgid "Month"
msgstr "月"

msgid "Week"
msgstr "星期"

msgid "Invalid value for %s: %s. Must be between %d and %d or '*'"
msgstr "%s: %s 的值无效. 必须在 %d 和 %d 之间,或为 '*'"

107 changes: 60 additions & 47 deletions applications/luci-app-timewol/root/etc/init.d/timewol
Original file line number Diff line number Diff line change
Expand Up @@ -2,73 +2,86 @@
#
# Copyright (C) 2015 OpenWrt-dist
# Copyright (C) 2016 fw867 <[email protected]>
# Copyright (C) 2024 iv7777 <[email protected]>
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#

START=99

CONFIG=timewol
CRONTAB_FILE="/etc/crontabs/root"
ETHERWAKE_CMD="/usr/bin/etherwake"

# Function to get UCI configuration values with defaults
uci_get_by_type() {
local index=0
if [ -n $4 ]; then
index=$4
fi
local ret=$(uci get $CONFIG.@$1[$index].$2 2>/dev/null)
echo ${ret:=$3}
local type=$1
local option=$2
local default=$3
local index=${4:-0} # Use 0 if $4 is not provided

local value
value=$(uci get "$CONFIG.@$type[$index].$option" 2>/dev/null) || value=$default
echo "$value"
}

# Function to check if a value represents a true boolean
is_true() {
case $1 in
1|on|true|yes|enabled) echo 0;;
*) echo 1;;
esac
case "$1" in
1|on|true|yes|enabled) return 0 ;;
*) return 1 ;;
esac
}

# Function to load configuration and check if enabled
load_config() {
ENABLED=$(uci_get_by_type basic enable)
return $(is_true $ENABLED)
local enabled
enabled=$(uci_get_by_type basic enable "0")
is_true "$enabled"
}

add_rule(){
sed -i '/etherwake/d' /etc/crontabs/root >/dev/null 2>&1
for i in $(seq 0 100)
do
local macaddr=$(uci_get_by_type macclient macaddr '' $i)
local maceth=$(uci_get_by_type macclient maceth '' $i)
local minute=$(uci_get_by_type macclient minute '' $i)
local hour=$(uci_get_by_type macclient hour '' $i)
local day=$(uci_get_by_type macclient day '' $i)
local month=$(uci_get_by_type macclient month '' $i)
local weeks=$(uci_get_by_type macclient weeks '' $i)
if [ -z $macaddr ] || [ -z $maceth ]; then
break
fi
if [ -z $minute ] ; then
minute="0"
fi
if [ -z $hour ] ; then
hour="*"
fi
if [ -z $day ] ; then
day="*"
fi
if [ -z $month ] ; then
month="*"
fi
if [ -z $weeks ] ; then
weeks="*"
fi
echo "$minute $hour $day $month $weeks /usr/bin/etherwake -D -i $maceth $macaddr" >> /etc/crontabs/root
done
# Function to add WoL rules to the crontab
add_rule() {
# Remove existing etherwake entries
sed -i '/etherwake/d' "$CRONTAB_FILE"

for i in $(seq 0 100); do
local macaddr
local maceth
local minute
local hour
local day
local month
local weeks

macaddr=$(uci_get_by_type macclient macaddr "" "$i")
maceth=$(uci_get_by_type macclient maceth "" "$i")

# Stop if no more macaddr entries
[ -z "$macaddr" ] && break
[ -z "$maceth" ] && break

minute=$(uci_get_by_type macclient minute "0" "$i")
hour=$(uci_get_by_type macclient hour "*" "$i")
day=$(uci_get_by_type macclient day "*" "$i")
month=$(uci_get_by_type macclient month "*" "$i")
weeks=$(uci_get_by_type macclient weeks "*" "$i")

echo "$minute $hour $day $month $weeks $ETHERWAKE_CMD -D -i $maceth $macaddr" >> "$CRONTAB_FILE"
done
}

# Function to start the service
start() {
! load_config && exit 0
add_rule
if load_config; then
add_rule
else
exit 0
fi
}

# Function to stop the service
stop() {
sed -i '/etherwake/d' /etc/crontabs/root >/dev/null 2>&1
# Remove etherwake entries from crontab
sed -i '/etherwake/d' "$CRONTAB_FILE"
}