From 496eaf6d5a9747a471221ced9abe6a3d6764fc8e Mon Sep 17 00:00:00 2001 From: iv7777 Date: Sat, 4 May 2024 12:22:28 -0700 Subject: [PATCH] luci-app-timewol: Script improvement and multilingualization Rewrite some scripts to make it work better and change to multilingual --- applications/luci-app-timewol/Makefile | 5 +- .../luasrc/controller/timewol.lua | 2 +- .../luasrc/model/cbi/timewol.lua | 123 ++++++++++++------ .../luci-app-timewol/po/zh_Hans/timewol.po | 52 ++++++++ .../luci-app-timewol/root/etc/init.d/timewol | 107 ++++++++------- 5 files changed, 202 insertions(+), 87 deletions(-) diff --git a/applications/luci-app-timewol/Makefile b/applications/luci-app-timewol/Makefile index 9ebdad42363..fec3f0578c8 100644 --- a/applications/luci-app-timewol/Makefile +++ b/applications/luci-app-timewol/Makefile @@ -1,4 +1,5 @@ # Copyright (C) 2016 Openwrt.org +# Copyright (C) 2024 iv7777 # # This is free software, licensed under the Apache License, Version 2.0 . # @@ -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 diff --git a/applications/luci-app-timewol/luasrc/controller/timewol.lua b/applications/luci-app-timewol/luasrc/controller/timewol.lua index afe6613c699..6a62a207b9a 100644 --- a/applications/luci-app-timewol/luasrc/controller/timewol.lua +++ b/applications/luci-app-timewol/luasrc/controller/timewol.lua @@ -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" } diff --git a/applications/luci-app-timewol/luasrc/model/cbi/timewol.lua b/applications/luci-app-timewol/luasrc/model/cbi/timewol.lua index 54b2c010a2a..092d8373a0a 100644 --- a/applications/luci-app-timewol/luasrc/model/cbi/timewol.lua +++ b/applications/luci-app-timewol/luasrc/model/cbi/timewol.lua @@ -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 + diff --git a/applications/luci-app-timewol/po/zh_Hans/timewol.po b/applications/luci-app-timewol/po/zh_Hans/timewol.po index a883cf73aba..994ea8b050a 100644 --- a/applications/luci-app-timewol/po/zh_Hans/timewol.po +++ b/applications/luci-app-timewol/po/zh_Hans/timewol.po @@ -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 之间,或为 '*'" + diff --git a/applications/luci-app-timewol/root/etc/init.d/timewol b/applications/luci-app-timewol/root/etc/init.d/timewol index 362c7395744..41f31de8627 100755 --- a/applications/luci-app-timewol/root/etc/init.d/timewol +++ b/applications/luci-app-timewol/root/etc/init.d/timewol @@ -2,73 +2,86 @@ # # Copyright (C) 2015 OpenWrt-dist # Copyright (C) 2016 fw867 +# Copyright (C) 2024 iv7777 # # 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" }