Cudy TR3000 OpenWrt 自定义 LED 灯:旁路由网络状态与夜间灯光控制

Cudy TR3000 刷入 OpenWrt 后作为旁路由使用,默认 LED 状态不能完全满足我的使用习惯。

这次通过 OpenWrt 的 procd 后台服务和 Shell 脚本,实现一套简单的 LED 状态控制:

  • 06:00~18:00:网络正常时,白灯常亮。
  • 18:00~06:00:网络正常时,白灯关闭。
  • 任何时间网络断开:红灯亮,白灯关闭。
  • 网络恢复后:红灯关闭,白灯按照当前时间自动恢复。
  • 路由器重启后:脚本自动启动。
  • 脚本异常退出后:由 procd 自动重新拉起。
  • 不写长期日志:避免脚本运行时间越长产生越来越多的日志文件。

整个方案的核心原则只有一句:

网络故障优先于时间规则。

所以即使是凌晨 2 点,只要网络断开,红灯依然会亮。


一、我的硬件与网络环境

当前环境:

  • Cudy TR3000
  • OpenWrt
  • 512MB RAM
  • 128MB Flash
  • 旁路由模式
  • 通过 LAN 口连接主路由
  • 安装 AdGuard Home

网络结构:

1
2
3
4
5
6
7
8
9
主路由
│
│ LAN 网线
▼
Cudy TR3000
│
└── OpenWrt 旁路由
│
└── AdGuard Home

旁路由模式下,不建议只使用 ifup/ifdown 判断网络是否正常。因为 LAN 作为桥接网络时,物理网线断开并不一定意味着 br-lan 立即进入 ifdown 状态。

因此本方案同时考虑:

  1. LAN 物理链路;
  2. Internet 连通性;
  3. 当前时间。

二、最终 LED 状态

时间 网络状态 白灯 红灯
06:00~18:00 正常 亮 灭
18:00~06:00 正常 灭 灭
任意时间 上联网线断开 灭 亮
任意时间 主路由断电 灭 亮
任意时间 Internet 断开 灭 亮
任意时间 网络恢复 按时间恢复 灭

优先级:

1
2
3
4
5
6
7
8
9
网络故障
↓
红灯亮、白灯灭
↓
只有网络正常时
↓
再判断当前时间
↓
控制白灯

例如:

1
2
3
4
5
6
7
8
9
10
11
23:00 + 正常联网
→ 白灯灭、红灯灭

23:00 + 网络断开
→ 白灯灭、红灯亮

10:00 + 正常联网
→ 白灯亮、红灯灭

10:00 + 网络断开
→ 白灯灭、红灯亮

三、确认 LED 节点

SSH 登录 TR3000:

1
ssh root@你的旁路由IP

查看 LED:

1
ls /sys/class/leds/

确认是否存在:

1
2
red:power
white:status

如果存在,先手动测试。

白灯

打开:

1
echo 255 > /sys/class/leds/white:status/brightness

关闭:

1
echo 0 > /sys/class/leds/white:status/brightness

红灯

打开:

1
echo 255 > /sys/class/leds/red:power/brightness

关闭:

1
echo 0 > /sys/class/leds/red:power/brightness

四条命令都正常后再继续。

不同固件的 LED 节点名称可能不同。如果实际名称不同,需要按照 ls /sys/class/leds/ 的结果修改后面的脚本。


四、确认旁路由的 LAN 设备

先查看网络设备:

1
ip -br link

再查看 LAN 使用的设备:

1
uci get network.lan.device

如果返回:

1
br-lan

说明 LAN 使用的是 br-lan。

继续查看 br-lan 下有哪些物理端口:

1
ls /sys/class/net/br-lan/brif/

可能看到:

1
2
3
4
lan1
lan2
lan3
lan4

也可能是其他名称。

测试物理链路

例如:

1
cat /sys/class/net/lan1/carrier

返回:

1
1

表示该物理端口当前存在链路。

返回:

1
0

表示该端口当前没有物理链路。

可以在网线插着时查看一次,然后拔掉主路由到 TR3000 的网线,再查看一次,用来确认实际的物理端口。

不要直接假定上联网口一定是 lan1。不同固件和网络配置下名称可能不同。


五、测试 Internet 连通性

测试:

1
ping -c 1 -W 1 223.5.5.5

再测试:

1
ping -c 1 -W 1 114.114.114.114

脚本会采用“两个目标只要有一个成功,就认为 Internet 正常”的方式,降低单个目标暂时不可达造成误判的概率。

也可以测试通过 LAN Bridge 检测:

1
ping -I br-lan -c 1 -W 1 223.5.5.5

六、关闭 OpenWrt 默认 LED 服务

为了避免系统自带 LED 服务与自定义脚本同时控制 LED,执行:

1
/etc/init.d/led stop

然后:

1
/etc/init.d/led disable

之后由自己的脚本负责 LED 状态。


七、创建 LED 控制脚本

创建:

1
vi /usr/bin/led-network-monitor.sh

写入以下完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
#!/bin/sh

# ==========================================================
# Cudy TR3000 OpenWrt LED Network Monitor
#
# 旁路由模式
#
# 白灯:
# 06:00 - 18:00 网络正常 -> 常亮
# 18:00 - 06:00 网络正常 -> 关闭
#
# 红灯:
# 任意时间网络异常 -> 亮
#
# 优先级:
# 网络故障 > 时间规则
# ==========================================================


# =========================
# LED
# =========================

WHITE_LED="/sys/class/leds/white:status/brightness"
RED_LED="/sys/class/leds/red:power/brightness"


# =========================
# LAN Bridge
# =========================

LAN_BR="br-lan"


# =========================
# Internet 检测地址
# =========================

PING1="223.5.5.5"
PING2="114.114.114.114"


# =========================
# 时间
# 18:00 ~ 06:00 为夜间
# =========================

NIGHT_START=18
NIGHT_END=6


# =========================
# 检测周期
# =========================

INTERVAL=15


# =========================
# 开机等待
# 给 OpenWrt / 网络 / AdGuard Home
# 一些初始化时间
# =========================

sleep 30


# =========================
# 检查 LED 节点
# =========================

[ -e "$WHITE_LED" ] || exit 1
[ -e "$RED_LED" ] || exit 1


# =========================
# 设置 LED
# =========================

set_led()
{
WHITE="$1"
RED="$2"

CURRENT_WHITE=$(cat "$WHITE_LED" 2>/dev/null)
CURRENT_RED=$(cat "$RED_LED" 2>/dev/null)

# 状态没有变化,不重复写
if [ "$CURRENT_WHITE" = "$WHITE" ] &&
[ "$CURRENT_RED" = "$RED" ]
then
return
fi

echo "$WHITE" > "$WHITE_LED"
echo "$RED" > "$RED_LED"
}


# =========================
# 获取当前小时
# =========================

get_hour()
{
date +%H | sed 's/^0//'
}


# =========================
# 判断是否夜间
# 18:00 ~ 06:00
# =========================

is_night()
{
H=$(get_hour)

if [ "$H" -ge "$NIGHT_START" ] ||
[ "$H" -lt "$NIGHT_END" ]
then
return 0
fi

return 1
}


# =========================
# 检查 Internet
#
# 两个地址只要一个成功
# 就认为网络正常
# =========================

internet_ok()
{
ping -I "$LAN_BR" -c 1 -W 1 "$PING1" \
>/dev/null 2>&1 && return 0

ping -I "$LAN_BR" -c 1 -W 1 "$PING2" \
>/dev/null 2>&1 && return 0

return 1
}


# =========================
# 检查 LAN 物理链路
#
# 检查 br-lan 下的物理端口
#
# 注意:
# 物理链路只是辅助判断,
# Internet 检测才是最终网络状态判断。
# =========================

lan_link_ok()
{
FOUND_PORT=0

for DEV in /sys/class/net/"$LAN_BR"/brif/*
do

[ -e "$DEV" ] || continue

PORT_NAME=$(basename "$DEV")
CARRIER_FILE="/sys/class/net/$PORT_NAME/carrier"

[ -f "$CARRIER_FILE" ] || continue

FOUND_PORT=1

LINK=$(cat "$CARRIER_FILE" 2>/dev/null)

if [ "$LINK" = "1" ]
then
return 0
fi

done

# 没有找到可检测的物理端口时,
# 不单独判定失败,交给 Internet 检测。

[ "$FOUND_PORT" = "0" ] && return 0

return 1
}


# =========================
# 主循环
# =========================

while true
do

# ======================================================
# 第一优先级:LAN 物理链路
# ======================================================

if ! lan_link_ok
then

# LAN 没有物理链路
# 红灯最高优先级

set_led 0 255

else

# ==================================================
# 第二优先级:Internet
# ==================================================

if ! internet_ok
then

# Internet 断开
# 红灯最高优先级

set_led 0 255

else

# ==================================================
# 第三优先级:时间
# ==================================================

if is_night
then

# 夜间正常联网
# 白灯灭
# 红灯灭

set_led 0 0

else

# 白天正常联网
# 白灯亮
# 红灯灭

set_led 255 0

fi

fi

fi

sleep "$INTERVAL"

done

保存并退出:

1
2
3
Esc
:wq
Enter

八、赋予执行权限

1
chmod +x /usr/bin/led-network-monitor.sh

九、先手动测试

正式设置开机启动之前,先运行:

1
/usr/bin/led-network-monitor.sh

脚本会先等待约 30 秒,然后开始判断。

白天正常联网:

1
2
白灯亮
红灯灭

晚上正常联网:

1
2
白灯灭
红灯灭

按:

1
Ctrl + C

可以停止手动测试。


十、测试拔掉主路由到 TR3000 的网线

白天正常联网时:

1
2
白灯亮
红灯灭

拔掉主路由与 TR3000 之间的网线。

当前检测周期是:

1
INTERVAL=15

所以通常最多约 15 秒后:

1
2
白灯灭
红灯亮

重新插回网线:

1
2
白灯恢复
红灯熄灭

十一、测试夜间断网

晚上 18:00 以后正常联网:

1
2
白灯灭
红灯灭

此时拔掉上联网线:

1
2
白灯灭
红灯亮

重新连接网络:

1
2
白灯灭
红灯灭

这就是本方案最重要的一点:

夜间只是关闭白灯,并不会关闭网络故障提示。


十二、创建 OpenWrt 后台服务

创建:

1
vi /etc/init.d/led-network

写入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/sh /etc/rc.common

START=99

USE_PROCD=1

start_service()
{
procd_open_instance

procd_set_param command \
/usr/bin/led-network-monitor.sh

# 脚本异常退出时自动重启
procd_set_param respawn

procd_close_instance
}

保存:

1
2
3
Esc
:wq
Enter

赋予权限:

1
chmod +x /etc/init.d/led-network

十三、设置开机自动启动

执行:

1
/etc/init.d/led-network enable

查看:

1
ls -l /etc/rc.d/ | grep led-network

正常应该看到:

1
S99led-network -> ../init.d/led-network

其中:

1
S99

就是启动顺序。

START=99 需要修改吗?

不需要。

保持:

1
START=99

即可。

脚本本身还有:

1
sleep 30

所以 OpenWrt 启动 LED 服务后,会再等待约 30 秒才开始第一次网络检测。


十四、启动服务

1
/etc/init.d/led-network start

查看进程:

1
ps | grep led-network

正常应该可以看到:

1
/usr/bin/led-network-monitor.sh

也可以查看:

1
ubus call service list | grep led-network -A 10

十五、测试路由器重启后是否自动运行

确认前面的功能都正常后:

1
reboot

等 OpenWrt 完成启动,再 SSH 登录。

执行:

1
ps | grep led-network

应该看到:

1
/usr/bin/led-network-monitor.sh

然后:

1
ls -l /etc/rc.d/ | grep led-network

应该仍然看到:

1
S99led-network -> ../init.d/led-network

这就表示:

1
2
3
4
5
6
7
8
9
路由器重启
↓
OpenWrt 启动
↓
led-network 自动启动
↓
等待 30 秒
↓
开始 LED 网络监控

不需要每次开机手动执行脚本。


十六、为什么这个脚本可以长期运行

脚本采用:

1
2
3
4
5
while true
do
...
sleep 15
done

但它不会保存历史数据,也不会创建不断增长的日志。

没有:

  • 数据库
  • 历史记录
  • 日志文件
  • 长期缓存
  • 不断增长的临时文件

因此脚本本身不会随着运行时间增加而越来越大。

LED 控制使用的是:

1
/sys/class/leds/

属于内核提供的虚拟接口,并不是持续写入 Flash 的普通文件。

因此:

不需要为了这个 LED 脚本定期重启路由器。

如果脚本因为某种原因异常退出:

1
procd_set_param respawn

会让 OpenWrt 自动重新启动它。


十七、参数说明

夜间时间

1
2
NIGHT_START=18
NIGHT_END=6

表示:

1
18:00 ~ 06:00

夜间关闭白灯。

例如改成 19:00~07:00:

1
2
NIGHT_START=19
NIGHT_END=7

网络检测间隔

1
INTERVAL=15

代表大约每 15 秒检查一次。

如果网络断开:

1
2
3
最多约 15 秒
↓
红灯亮

网络恢复:

1
2
3
4
5
最多约 15 秒
↓
重新判断
↓
LED 恢复

对于状态灯来说,15 秒已经比较及时。


开机等待

1
sleep 30

表示路由器启动后先等待约 30 秒,再进行第一次网络状态判断。

这样可以避免 OpenWrt、网络和 AdGuard Home 刚启动时,由于网络还没完全建立而短暂显示红灯。


十八、最终文件结构

最终只需要两个主要文件:

1
/usr/bin/led-network-monitor.sh

负责:

1
2
3
4
物理链路检测
Internet 检测
时间判断
LED 控制

以及:

1
/etc/init.d/led-network

负责:

1
2
3
开机自动启动
procd 守护
异常自动重启

十九、最终效果

完成以后,TR3000 的 LED 逻辑就是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
          开机
│
▼
等待30秒
│
▼
检查 LAN 链路
│
┌───────┴───────┐
│ │
异常 正常
│ │
▼ ▼
红灯亮 检查 Internet
│
┌──────┴──────┐
│ │
断网 正常
│ │
▼ ▼
红灯亮 判断时间
│
┌────────┴────────┐
│ │
18:00~06:00 06:00~18:00
│ │
▼ ▼
全灭 白灯常亮

最终实现:

正常联网时,白灯只在白天亮,夜间自动熄灭;任何时间网络出现故障,红灯优先亮起;网络恢复后自动恢复到对应时间的 LED 状态。

这套方案不需要修改 OpenWrt 网络配置,适合直接作为 Cudy TR3000 旁路由的长期 LED 状态控制方案。


本站由 doyoudo 使用 Stellar 2.0.0 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
Copyright@2022-2026

站内搜索

没有找到内容!