🤞 Sync 2026-07-14 23:59:34

This commit is contained in:
github-actions[bot] 2026-07-14 23:59:34 +08:00
parent 09a1b41f45
commit ce598ef156
14 changed files with 254 additions and 95 deletions

View File

@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall PKG_NAME:=luci-app-passwall
PKG_VERSION:=26.7.1 PKG_VERSION:=26.7.1
PKG_RELEASE:=178 PKG_RELEASE:=179
PKG_PO_VERSION:=$(PKG_VERSION) PKG_PO_VERSION:=$(PKG_VERSION)
PKG_CONFIG_DEPENDS:= \ PKG_CONFIG_DEPENDS:= \

View File

@ -81,23 +81,14 @@ o = s:option(Flag, "enable_autoswitch", translate("Auto Switch"))
o.default = 0 o.default = 0
o.rmempty = false o.rmempty = false
o = s:option(Value, "autoswitch_testing_time", translate("How often to test"), translate("Units:seconds")) o = s:option(ListValue, "backup_node_add_mode", translate("Backup Node Addition Method"))
o.datatype = "min(10)"
o.default = 30
o:depends("enable_autoswitch", true)
o = s:option(Value, "autoswitch_connect_timeout", translate("Timeout seconds"), translate("Units:seconds"))
o.datatype = "min(1)"
o.default = 3
o:depends("enable_autoswitch", true)
o = s:option(Value, "autoswitch_retry_num", translate("Timeout retry num"))
o.datatype = "min(1)"
o.default = 1
o:depends("enable_autoswitch", true) o:depends("enable_autoswitch", true)
o.default = "manual"
o:value("manual", translate("Manual"))
o:value("batch", translate("Batch"))
o = s:option(DynamicList, "autoswitch_backup_node", translate("List of backup nodes")) o = s:option(DynamicList, "autoswitch_backup_node", translate("List of backup nodes"))
o:depends("enable_autoswitch", true) o:depends("backup_node_add_mode", "manual")
o.template = appname .. "/cbi/nodes_dynamiclist" o.template = appname .. "/cbi/nodes_dynamiclist"
o.group = {} o.group = {}
o.write = function(self, section, value) o.write = function(self, section, value)
@ -119,6 +110,44 @@ for i, v in pairs(nodes_table) do
socks_node.group[#socks_node.group+1] = (v.group and v.group ~= "") and v.group or translate("default") socks_node.group[#socks_node.group+1] = (v.group and v.group ~= "") and v.group or translate("default")
end end
o = s:option(MultiValue, "backup_node_group", translate("Select Group"))
o:depends("backup_node_add_mode", "batch")
o.widget = "checkbox"
o:value("default", translate("default"))
local groups = {}
m.uci:foreach(appname, "nodes", function(s)
if s.group and s.group ~= "" then
groups[s.group] = true
end
end)
for k, v in pairs(groups) do
o:value(api.UrlEncode(k), k)
end
o = s:option(Value, "backup_node_match_rule", translate("Node Matching Rules"))
o:depends("backup_node_add_mode", "batch")
local descrStr = "Example: <code>^A && B && !C && D$</code><br>"
descrStr = descrStr .. "This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>"
descrStr = descrStr .. "Conditions are joined by <code>&&</code> (AND), and their order does not affect the result.<br>"
descrStr = descrStr .. "Multiple groups can be separated by <code>||</code> (OR), matching succeeds if any group matches.<br>"
descrStr = descrStr .. "Example: <code>A && B || C && D</code> means (A AND B) OR (C AND D)."
o.description = translate(descrStr)
o = s:option(Value, "autoswitch_testing_time", translate("How often to test"), translate("Units:seconds"))
o.datatype = "min(10)"
o.default = 30
o:depends("enable_autoswitch", true)
o = s:option(Value, "autoswitch_connect_timeout", translate("Timeout seconds"), translate("Units:seconds"))
o.datatype = "min(1)"
o.default = 3
o:depends("enable_autoswitch", true)
o = s:option(Value, "autoswitch_retry_num", translate("Timeout retry num"))
o.datatype = "min(1)"
o.default = 1
o:depends("enable_autoswitch", true)
o = s:option(Flag, "autoswitch_restore_switch", translate("Restore Switch"), translate("When detects main node is available, switch back to the main node.")) o = s:option(Flag, "autoswitch_restore_switch", translate("Restore Switch"), translate("When detects main node is available, switch back to the main node."))
o:depends("enable_autoswitch", true) o:depends("enable_autoswitch", true)
@ -135,6 +164,6 @@ o:depends("enable_autoswitch", true)
o = s:option(DummyValue, "btn") o = s:option(DummyValue, "btn")
o.template = appname .. "/socks_auto_switch/btn" o.template = appname .. "/socks_auto_switch/btn"
o:depends("enable_autoswitch", true) o:depends("backup_node_add_mode", "manual")
return m return m

View File

@ -1598,6 +1598,56 @@ function match_node_rule(name, rule)
return false return false
end end
local normal_nodes = {}
function get_batch_nodes(node)
if #normal_nodes == 0 then
for k, e in ipairs(get_valid_nodes()) do
if e.node_type == "normal" and (not e.chain_proxy or e.chain_proxy == "") then
normal_nodes[#normal_nodes + 1] = {
id = e[".name"],
remarks = e["remarks"],
group = e["group"]
}
end
end
end
if not node.node_group or node.node_group == "" then return {} end
local nodes = {}
for g in node.node_group:gmatch("%S+") do
g = UrlDecode(g)
for k, v in pairs(normal_nodes) do
local gn = (v.group and v.group ~= "") and v.group or "default"
if gn:lower() == g:lower() and match_node_rule(v.remarks, node.node_match_rule) then
nodes[#nodes + 1] = v.id
end
end
end
return nodes
end
function get_socks_backup_nodes(id)
id = trim(id)
if id == "" then return "" end
local socks = uci:get_all(appname, id)
local nodes
if socks.backup_node_add_mode and socks.backup_node_add_mode == "batch" then
local node = {}
node.node_group = socks.backup_node_group
node.node_match_rule = socks.backup_node_match_rule
nodes = get_batch_nodes(node)
else
nodes = socks.autoswitch_backup_node
end
local backup_nodes, seen = {}, {}
for _, v in ipairs(nodes or {}) do
if v ~= socks.node and not seen[v] then
seen[v] = true
table.insert(backup_nodes, v)
end
end
return table.concat(backup_nodes, " ")
end
function get_core(field, candidates) function get_core(field, candidates)
local v = uci:get(appname, "@global_subscribe[0]", field) local v = uci:get(appname, "@global_subscribe[0]", field)
if v and v ~= "" then if v and v ~= "" then

View File

@ -1285,33 +1285,6 @@ function gen_config(var)
return result return result
end end
local nodes_list = {}
function get_urltest_batch_nodes(_node)
if #nodes_list == 0 then
for k, e in ipairs(api.get_valid_nodes()) do
if e.node_type == "normal" and (not e.chain_proxy or e.chain_proxy == "") then
nodes_list[#nodes_list + 1] = {
id = e[".name"],
remarks = e["remarks"],
group = e["group"]
}
end
end
end
if not _node.node_group or _node.node_group == "" then return {} end
local nodes = {}
for g in _node.node_group:gmatch("%S+") do
g = api.UrlDecode(g)
for k, v in pairs(nodes_list) do
local gn = (v.group and v.group ~= "") and v.group or "default"
if gn:lower() == g:lower() and api.match_node_rule(v.remarks, _node.node_match_rule) then
nodes[#nodes + 1] = v.id
end
end
end
return nodes
end
function get_node_by_id(node_id) function get_node_by_id(node_id)
if not node_id or node_id == "" or node_id == "nil" then return nil end if not node_id or node_id == "" or node_id == "nil" then return nil end
if node_id:find("Socks_") then if node_id:find("Socks_") then
@ -1333,7 +1306,7 @@ function gen_config(var)
-- new urltest -- new urltest
local ut_nodes local ut_nodes
if _node.node_add_mode and _node.node_add_mode == "batch" then if _node.node_add_mode and _node.node_add_mode == "batch" then
ut_nodes = get_urltest_batch_nodes(_node) ut_nodes = api.get_batch_nodes(_node)
else else
ut_nodes = _node.urltest_node ut_nodes = _node.urltest_node
end end

View File

@ -1016,33 +1016,6 @@ function gen_config(var)
end end
end end
local nodes_list = {}
function get_balancer_batch_nodes(_node)
if #nodes_list == 0 then
for k, e in ipairs(api.get_valid_nodes()) do
if e.node_type == "normal" and (not e.chain_proxy or e.chain_proxy == "") then
nodes_list[#nodes_list + 1] = {
id = e[".name"],
remarks = e["remarks"],
group = e["group"]
}
end
end
end
if not _node.node_group or _node.node_group == "" then return {} end
local nodes = {}
for g in _node.node_group:gmatch("%S+") do
g = api.UrlDecode(g)
for k, v in pairs(nodes_list) do
local gn = (v.group and v.group ~= "") and v.group or "default"
if gn:lower() == g:lower() and api.match_node_rule(v.remarks, _node.node_match_rule) then
nodes[#nodes + 1] = v.id
end
end
end
return nodes
end
function gen_loopback(outbound_tag, loopback_dst) function gen_loopback(outbound_tag, loopback_dst)
if not outbound_tag or outbound_tag == "" then return nil end if not outbound_tag or outbound_tag == "" then return nil end
local inbound_tag = loopback_dst and "lo-to-" .. loopback_dst or outbound_tag .. "-lo" local inbound_tag = loopback_dst and "lo-to-" .. loopback_dst or outbound_tag .. "-lo"
@ -1074,7 +1047,7 @@ function gen_config(var)
-- new balancer -- new balancer
local blc_nodes local blc_nodes
if _node.node_add_mode and _node.node_add_mode == "batch" then if _node.node_add_mode and _node.node_add_mode == "batch" then
blc_nodes = get_balancer_batch_nodes(_node) blc_nodes = api.get_batch_nodes(_node)
else else
blc_nodes = _node.balancing_node blc_nodes = _node.balancing_node
end end

View File

@ -517,6 +517,9 @@ msgstr "负载均衡"
msgid "Node Addition Method" msgid "Node Addition Method"
msgstr "节点添加方式" msgstr "节点添加方式"
msgid "Backup Node Addition Method"
msgstr "后备节点添加方式"
msgid "Manual" msgid "Manual"
msgstr "手动" msgstr "手动"

View File

@ -998,7 +998,6 @@ start_socks() {
local http_port=$(config_n_get $id http_port 0) local http_port=$(config_n_get $id http_port 0)
local http_config_file="HTTP2SOCKS_${id}.json" local http_config_file="HTTP2SOCKS_${id}.json"
local enable_autoswitch=$(config_n_get $id enable_autoswitch 0) local enable_autoswitch=$(config_n_get $id enable_autoswitch 0)
[ "$enable_autoswitch" = "1" ] && [ -z "$(config_n_get $id autoswitch_backup_node)" ] && enable_autoswitch=0
local no_rec=0 local no_rec=0
[ "$enable_autoswitch" = "1" ] && no_rec=1 [ "$enable_autoswitch" = "1" ] && no_rec=1
NO_REC_PROCESS=$no_rec $APP_PATH/app.sh run_socks flag=$id node=$node bind=$bind socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file log_file=$log_file NO_REC_PROCESS=$no_rec $APP_PATH/app.sh run_socks flag=$id node=$node bind=$bind socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file log_file=$log_file

View File

@ -164,14 +164,15 @@ start() {
retry_num=$(config_n_get $id autoswitch_retry_num 1) retry_num=$(config_n_get $id autoswitch_retry_num 1)
restore_switch=$(config_n_get $id autoswitch_restore_switch 0) restore_switch=$(config_n_get $id autoswitch_restore_switch 0)
probe_url=$(config_n_get $id autoswitch_probe_url "https://www.google.com/generate_204") probe_url=$(config_n_get $id autoswitch_probe_url "https://www.google.com/generate_204")
backup_node=$(config_n_get $id autoswitch_backup_node) backup_node=$(lua_api "get_socks_backup_nodes(\"${id}\")")
if [ -n "$backup_node" ]; then if [ -n "$backup_node" ]; then
backup_node=$(echo "$backup_node" | tr -s ' ' '\n' | uniq | tr -s '\n' ' ')
backup_node_num=$(printf "%s\n" "$backup_node" | wc -w) backup_node_num=$(printf "%s\n" "$backup_node" | wc -w)
echolog " - Socks切换检测端口[${socks_port}] 后备节点数量:${backup_node_num}"
if [ "$backup_node_num" -eq 1 ]; then if [ "$backup_node_num" -eq 1 ]; then
[ "$main_node" = "$backup_node" ] && return [ "$main_node" = "$backup_node" ] && return
fi fi
else else
echolog " - Socks切换检测端口[${socks_port}] 后备节点数量0"
return return
fi fi
while [ -n "$backup_node" ]; do while [ -n "$backup_node" ]; do

View File

@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall2 PKG_NAME:=luci-app-passwall2
PKG_VERSION:=26.7.12 PKG_VERSION:=26.7.12
PKG_RELEASE:=61 PKG_RELEASE:=62
PKG_PO_VERSION:=$(PKG_VERSION) PKG_PO_VERSION:=$(PKG_VERSION)
PKG_CONFIG_DEPENDS:= \ PKG_CONFIG_DEPENDS:= \

View File

@ -922,10 +922,10 @@ function gen_config(var)
fragment_table = { fragment_table = {
type = "fragment", type = "fragment",
settings = { settings = {
packets = xray_settings.fragment_packets, packets = xray_settings.fragment_packets or "tlshello",
lengths = #lengths > 0 and lengths or nil, lengths = #lengths > 0 and lengths or {"3-5","6-8","10-20"},
delays = #delays > 0 and delays or nil, delays = #delays > 0 and delays or {"10-20"},
maxSplit = xray_settings.fragment_maxSplit maxSplit = xray_settings.fragment_maxSplit or "3-6"
} }
} }
end end

View File

@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-wechatpush PKG_NAME:=luci-app-wechatpush
PKG_VERSION:=3.6.12 PKG_VERSION:=3.6.12
PKG_RELEASE:=5 PKG_RELEASE:=6
PKG_MAINTAINER:=tty228 <tty228@yeah.net> PKG_MAINTAINER:=tty228 <tty228@yeah.net>
PKG_CONFIG_DEPENDS:= \ PKG_CONFIG_DEPENDS:= \

View File

@ -1342,6 +1342,15 @@ msgstr "设备状态变化"
msgid "Traffic in 1 minute:" msgid "Traffic in 1 minute:"
msgstr "一分钟内流量:" msgstr "一分钟内流量:"
msgid "Upload Traffic:"
msgstr "上传流量:"
msgid "Download Traffic:"
msgstr "下载流量:"
msgid "Signal Strength:"
msgstr "dBm"
msgid "Whitelist add failed, IP format error" msgid "Whitelist add failed, IP format error"
msgstr "白名单添加失败IP 格式错误" msgstr "白名单添加失败IP 格式错误"

View File

@ -123,6 +123,40 @@ read_config() {
cron cron
} }
get_signal_dbm() {
local mac="$1"
local device
local wxjk_dbm
[ -z "$mac" ] && return 1
echo "$mac" | grep -qE "^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$" || return 1
for device in /sys/class/net/*; do
device=$(basename "$device")
[ -d "/sys/class/net/$device/wireless" ] || continue
iwinfo "$device" info >/dev/null 2>&1 || continue
wxjk_dbm=$(iwinfo "$device" assoclist 2>/dev/null | awk -v mac="$mac" '
index(tolower($0), tolower(mac)) {
line = tolower($0)
if (match(line, /-?[0-9]+[[:space:]]*dbm/)) {
val = substr(line, RSTART, RLENGTH)
gsub(/[[:space:]]*dbm/, "", val)
print val
} else {
print "__SEEN__"
}
exit
}
')
[ "$wxjk_dbm" = "__SEEN__" ] && return 1
[ -n "$wxjk_dbm" ] && echo "$wxjk_dbm" | awk '{ $1=$1 };1' && return 0
done
return 1
}
# 初始化 # 初始化
init() { init() {
# 检测程序开关 # 检测程序开关
@ -968,9 +1002,22 @@ usage() {
elif [ $1 == "get" ]; then elif [ $1 == "get" ]; then
[ ! -f "${dir}/usage.db" ] && [ -z "$3" ] && echo $(bytes_for_humans "0") && return [ ! -f "${dir}/usage.db" ] && [ -z "$3" ] && echo $(bytes_for_humans "0") && return
[ ! -f "${dir}/usage.db" ] && [ -n "$3" ] && echo "0" && return [ ! -f "${dir}/usage.db" ] && [ -n "$3" ] && echo "0" && return
[ -z "$total_n" ] && total_n=$(cat ${dir}/usage.db | head -n1 | grep "total" | sed 's/,/\n/g' | awk '/total/{print NR}') 2>/dev/null [ -z "$total_n" ] && total_n=$(head -n1 "${dir}/usage.db" | sed 's/,/\n/g' | awk '$0=="total"{print NR; exit}') 2>/dev/null
[ -z "$in_n" ] && in_n=$(head -n1 "${dir}/usage.db" | sed 's/,/\n/g' | awk '$0=="in"{print NR; exit}') 2>/dev/null
[ -z "$out_n" ] && out_n=$(head -n1 "${dir}/usage.db" | sed 's/,/\n/g' | awk '$0=="out"{print NR; exit}') 2>/dev/null
[ -z "$total_n" ] && total_n="6" [ -z "$total_n" ] && total_n="6"
[ -n "$2" ] && local tmptotal=$(cat ${dir}/usage.db | sed 's/,,,/,0,0,/g' | sed 's/,,/,0,/g' | sed 's/,/ /g' | grep -i -w ${2} | awk "{print "'$'$total_n"}" | grep -v "^$" | sort -u | head -n1) 2>/dev/null local selected_n="$total_n"
case "$4" in
in) selected_n="$in_n" ;;
out) selected_n="$out_n" ;;
total|"") selected_n="$total_n" ;;
*) selected_n="$total_n" ;;
esac
case "$4" in
in|out) [ -z "$selected_n" ] && return ;;
*) [ -z "$selected_n" ] && selected_n="$total_n" ;;
esac
[ -n "$2" ] && local tmptotal=$(cat "${dir}/usage.db" | sed 's/,,,/,0,0,/g' | sed 's/,,/,0,/g' | sed 's/,/ /g' | awk -v key="$2" -v column="$selected_n" '{for (i=1; i<=NF; i++) if (tolower($i)==tolower(key)) {print $column; exit}}' | grep -v "^$" | sort -u | head -n1) 2>/dev/null
[ -z "$tmptotal" ] && local tmptotal="0" [ -z "$tmptotal" ] && local tmptotal="0"
[ -z "$3" ] && echo $(bytes_for_humans "${tmptotal}") || echo "$tmptotal" [ -z "$3" ] && echo $(bytes_for_humans "${tmptotal}") || echo "$tmptotal"
# 剔除 # 剔除
@ -979,6 +1026,44 @@ usage() {
fi fi
} }
get_usage_stats() {
local mac="$1"
local has_direction="0"
if [ ! -f "/usr/sbin/wrtbwmon" ] || [ -z "$mac" ] || [ ! -f "${dir}/usage.db" ]; then
echo "0 0 0 0"
return
fi
[ -z "$total_n" ] && total_n=$(head -n1 "${dir}/usage.db" | sed 's/,/\n/g' | awk '$0=="total"{print NR; exit}') 2>/dev/null
[ -z "$in_n" ] && in_n=$(head -n1 "${dir}/usage.db" | sed 's/,/\n/g' | awk '$0=="in"{print NR; exit}') 2>/dev/null
[ -z "$out_n" ] && out_n=$(head -n1 "${dir}/usage.db" | sed 's/,/\n/g' | awk '$0=="out"{print NR; exit}') 2>/dev/null
[ -z "$total_n" ] && total_n="6"
[ -n "$in_n" ] && [ -n "$out_n" ] && has_direction="1"
awk -F, -v key="$mac" -v total_col="$total_n" -v in_col="$in_n" -v out_col="$out_n" -v has_direction="$has_direction" '
{
for (i = 1; i <= NF; i++) {
if (tolower($i) == tolower(key)) {
total = $total_col + 0
in_bytes = 0
out_bytes = 0
if (has_direction == "1") {
in_bytes = $in_col + 0
out_bytes = $out_col + 0
}
print total, in_bytes, out_bytes, has_direction
found = 1
exit
}
}
}
END {
if (!found) print 0, 0, 0, has_direction
}
' "${dir}/usage.db" 2>/dev/null
}
# ------------------------------------ # ------------------------------------
# 需要经常调用的偷懒类 # 需要经常调用的偷懒类
# #
@ -1829,7 +1914,13 @@ ${str_linefeed}${str_tab} - $(translate "Client IP:")${str_space}${str_space}${s
${str_linefeed}${str_tab} - $(translate "Client MAC:")${str_space}${str_space}${str_space}${str_space}${mac}\ ${str_linefeed}${str_tab} - $(translate "Client MAC:")${str_space}${str_space}${str_space}${str_space}${mac}\
${str_linefeed}${str_tab} - $(translate "Network Interface:")${str_space}${str_space}${str_space}${str_space}${str_space}${interface}" ${str_linefeed}${str_tab} - $(translate "Network Interface:")${str_space}${str_space}${str_space}${str_space}${str_space}${interface}"
log_change "${disturb_text} $(translate "New device %s %s connected" "$name" "$ip")" local up_dbm=$(get_signal_dbm "$mac")
[ -n "$up_dbm" ] && content="${content}\
${str_linefeed}${str_tab} - $(translate "Signal Strength:")${str_space}${str_space}${up_dbm} dBm"
local up_log=$(translate "New device %s %s connected" "$name" "$ip")
[ -n "$up_dbm" ] && up_log="${up_log} dbm:${up_dbm}"
log_change "${disturb_text} ${up_log}"
[ -n "$title" ] && echo "$title" >"${dir}/title" [ -n "$title" ] && echo "$title" >"${dir}/title"
[ -n "$content" ] && echo -n "$content" >>"${dir}/content" [ -n "$content" ] && echo -n "$content" >>"${dir}/content"
@ -2065,16 +2156,24 @@ get_client_usage() {
if [ "$(($(date +%s) - $get_client_usage_time))" -ge "60" ]; then if [ "$(($(date +%s) - $get_client_usage_time))" -ge "60" ]; then
>${dir}/client_usage_aliases >${dir}/client_usage_aliases
for mac in $MACLIST; do for mac in $MACLIST; do
echo "$mac" $(usage get ${mac} bytes) >>${dir}/client_usage_aliases local cur_total cur_in cur_out cur_has_direction
[ -f "${dir}/old_client_usage_aliases" ] && get_client_usage_bytes=$(cat ${dir}/old_client_usage_aliases | grep -i -w $mac | awk '{print $2}' | grep -v "^$" | sort -u | head -n1) || continue read -r cur_total cur_in cur_out cur_has_direction <<<"$(get_usage_stats "$mac")"
echo "$mac ${cur_total} ${cur_in} ${cur_out} ${cur_has_direction}" >>${dir}/client_usage_aliases
[ -f "${dir}/old_client_usage_aliases" ] || continue
local old_line=$(awk -v key="$mac" 'tolower($1)==tolower(key){print; exit}' "${dir}/old_client_usage_aliases" 2>/dev/null)
[ -z "$old_line" ] && continue
[ -z "$get_client_usage_bytes" ] && get_client_usage_bytes="0" local old_mac prev_total prev_in prev_out old_has_direction
if [ "$(($(usage get ${mac} bytes) - $get_client_usage_bytes))" -ge "$client_usage_max" ]; then read -r old_mac prev_total prev_in prev_out old_has_direction <<<"$old_line"
[ -z "$prev_total" ] && prev_total="0"
local delta_total=$((cur_total - prev_total))
[ "$delta_total" -lt "0" ] && continue
if [ "$delta_total" -ge "$client_usage_max" ]; then
local ip=$(jq -r --arg mac "$mac" '.devices[] | select((.mac | ascii_downcase) == ($mac | ascii_downcase) and .status == "online") | .ip' "$devices_json") local ip=$(jq -r --arg mac "$mac" '.devices[] | select((.mac | ascii_downcase) == ($mac | ascii_downcase) and .status == "online") | .ip' "$devices_json")
local ip_name=$(getname ${ip} ${mac}) local ip_name=$(getname ${ip} ${mac})
local tmp_usage=$(bytes_for_humans $(expr $(usage get ${mac} bytes) - ${get_client_usage_bytes})) local tmp_usage=$(bytes_for_humans "$delta_total")
local time_up=$(jq -r --arg mac "$mac" '.devices[] | select((.mac | ascii_downcase) == ($mac | ascii_downcase) and .status == "online") | .uptime' "$devices_json") local time_up=$(jq -r --arg mac "$mac" '.devices[] | select((.mac | ascii_downcase) == ($mac | ascii_downcase) and .status == "online") | .uptime' "$devices_json")
local ip_total=$(usage get $mac) && [ -n "$ip_total" ] && local ip_total="${str_linefeed}${str_tab} - $(translate "Total Traffic:") ${str_space}${str_space}${str_space}${str_space}${ip_total}" local ip_total=$(bytes_for_humans "$cur_total") && [ -n "$ip_total" ] && local ip_total="${str_linefeed}${str_tab} - $(translate "Total Traffic:") ${str_space}${str_space}${str_space}${str_space}${ip_total}"
local time1=$(date +%s) local time1=$(date +%s)
local time1=$(time_for_humans $(expr ${time1} - ${time_up})) local time1=$(time_for_humans $(expr ${time1} - ${time_up}))
@ -2088,14 +2187,31 @@ get_client_usage() {
local content_title="${str_splitline}${str_title_start}$(translate "Device abnormal traffic")${str_title_end}" local content_title="${str_splitline}${str_title_start}$(translate "Device abnormal traffic")${str_title_end}"
fi fi
local detail_upload=""
local detail_download=""
if [ "$cur_has_direction" = "1" ] && [ "$old_has_direction" = "1" ]; then
[ -z "$prev_in" ] && prev_in="0"
[ -z "$prev_out" ] && prev_out="0"
local delta_in=$((cur_in - prev_in))
local delta_out=$((cur_out - prev_out))
[ "$delta_in" -lt "0" ] && delta_in="0"
[ "$delta_out" -lt "0" ] && delta_out="0"
detail_upload="${str_linefeed}${str_tab} - $(translate "Upload Traffic:")${str_space}${str_space}$(bytes_for_humans "$delta_out")"
detail_download="${str_linefeed}${str_tab} - $(translate "Download Traffic:")${str_space}$(bytes_for_humans "$delta_in")"
fi
local detail_dbm=""
local wxjk_dbm=$(get_signal_dbm "$mac")
[ -n "$wxjk_dbm" ] && detail_dbm="${str_linefeed}${str_tab} - $(translate "Signal Strength:")${str_space}${str_space}${wxjk_dbm} dBm"
content="\ content="\
${content}\ ${content}\
${content_title}\ ${content_title}\
${str_linefeed}${str_tab} - $(translate "Client Name:")${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}\ ${str_linefeed}${str_tab} - $(translate "Client Name:")${str_space}${str_space}${str_space}${str_space}${str_space}${ip_name}\
${str_linefeed}${str_tab} - $(translate "Client IP:")${str_space}${str_space}${str_space}${str_space}${ip}\ ${str_linefeed}${str_tab} - $(translate "Client IP:")${str_space}${str_space}${str_space}${str_space}${ip}\
${str_linefeed}${str_tab} - $(translate "Client MAC:")${str_space}${str_space}${str_space}${str_space}${mac}${ip_total}\ ${str_linefeed}${str_tab} - $(translate "Client MAC:")${str_space}${str_space}${str_space}${str_space}${mac}${ip_total}\
${str_linefeed}${str_tab} - $(translate "Traffic in 1 minute:")${str_space}${str_space}${str_space}${tmp_usage}\ ${str_linefeed}${str_tab} - $(translate "Traffic in 1 minute:")${str_space}${str_space}${str_space}${tmp_usage}${detail_upload}${detail_download}\
${str_linefeed}${str_tab} - $(translate "Uptime:")${str_space}${str_space}${str_space}${str_space}${time1}" ${str_linefeed}${str_tab} - $(translate "Uptime:")${str_space}${str_space}${str_space}${str_space}${time1}${detail_dbm}"
fi fi
done done
cat ${dir}/client_usage_aliases >${dir}/old_client_usage_aliases cat ${dir}/client_usage_aliases >${dir}/old_client_usage_aliases
@ -2657,7 +2773,13 @@ ${str_linefeed}${str_tab} - $(translate "Client IP:")${str_space}${str_space}${s
${str_linefeed}${str_tab} - $(translate "Client MAC:")${str_space}${str_space}${str_space}${str_space}${mac}${ip_total}\ ${str_linefeed}${str_tab} - $(translate "Client MAC:")${str_space}${str_space}${str_space}${str_space}${mac}${ip_total}\
${str_linefeed}${str_tab} - $(translate "Uptime:")${str_space}${str_space}${str_space}${str_space}${time1}" ${str_linefeed}${str_tab} - $(translate "Uptime:")${str_space}${str_space}${str_space}${str_space}${time1}"
log_change "${disturb_text} $(translate "Device %s %s disconnected" "$name" "$ip")" local down_dbm=$(get_signal_dbm "$mac")
[ -n "$down_dbm" ] && content="${content}\
${str_linefeed}${str_tab} - $(translate "Signal Strength:")${str_space}${str_space}${down_dbm} dBm"
local down_log=$(translate "Device %s %s disconnected" "$name" "$ip")
[ -n "$down_dbm" ] && down_log="${down_log} dbm:${down_dbm}"
log_change "${disturb_text} ${down_log}"
done done
silent_run LockFile lock silent_run LockFile lock

View File

@ -5,12 +5,12 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=rtl8189es PKG_NAME:=rtl8189es
PKG_RELEASE:=2 PKG_RELEASE:=3
PKG_SOURCE_URL:=https://github.com/jwrdegoede/rtl8189ES_linux.git PKG_SOURCE_URL:=https://github.com/jwrdegoede/rtl8189ES_linux.git
PKG_SOURCE_PROTO:=git PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2025-09-27 PKG_SOURCE_DATE:=2025-09-27
PKG_SOURCE_VERSION:=36d917d5069f25f4c36b8b4d8b17b5d02e9116e9 PKG_SOURCE_VERSION:=2d9a8afb5d12de1cfc4ab5ad3d1a61e1937629bd
PKG_MIRROR_HASH:=skip PKG_MIRROR_HASH:=skip
PKG_BUILD_PARALLEL:=1 PKG_BUILD_PARALLEL:=1