TP-Link TL-WR703n Reset按钮功能扩展——wifi模式切换

首先参考openwrt官网文档:《Attach functions to a push button

缘由:我的openwrt无线配置成客户端模式,在家自动连接家里的路由(配置一),在公司自动连接公司路由(配置二),但是如果在配置文件/etc/config/wireless同时指定这两种客户端模式配置,openwrt不会在其中一个配置连接失败后自动尝试另外一个配置连接。也就是说两种客户端模式配置,实际上只有其中一个有效(貌似谁写在前面谁生效)。这样,每次更换环境,都要先用一根网线连接到wr703n的LAN口,配置好笔记本的LAN网卡IP地址为192.168.1.2,以root ssh登陆进192.168.1.1,编辑wireless配置文件,禁用其中一种客户端模式(option disabled ‘1’),再重启网络才能让wr703n连接到主路由。整个过程太繁琐了。

另一种方式可以省去网线连接LAN口,就是让wr703n每次都以AP模式启动,笔记本电脑再通过无线连接wr703n,连上之后就可以ssh登陆进去,然后改配置并重启网络,过程也不简洁。

先贴出目前openwrt的网络配置:

# cat /etc/config/wireless

config wifi-device ‘radio0’
option type ‘mac80211’
option channel ‘11’
option macaddr ‘1c:fa:68:f9:f3:4a’
option hwmode ‘11ng’
option htmode ‘HT20’
list ht_capab ‘SHORT-GI-20’
list ht_capab ‘SHORT-GI-40’
list ht_capab ‘RX-STBC1’
list ht_capab ‘DSSS_CCK-40’

config wifi-iface ‘ap’
option device ‘radio0’
option network ‘wlan’
option mode ‘ap’
option ssid ‘OpenWrt’
option encryption ‘none’
option disabled ‘0’

config wifi-iface ‘company’
option network ‘wwan’
option ssid ‘company_ssid’
option encryption ‘psk2’
option device ‘radio0’
option mode ‘sta’
option bssid ‘00:13:10:41:69:EE’
option key ‘xxxxxxxx’
option disabled ‘0’

config wifi-iface ‘home’
option network ‘wwan’
option ssid ‘home_ssid’
option encryption ‘psk2’
option device ‘radio0’
option mode ‘sta’
option bssid ‘00:21:29:74:33:EB’
option key ‘xxxxxxxx’
option wds ‘1’
option disabled ‘1’

cat /etc/config/network

config interface ‘loopback’
option ifname ‘lo’
option proto ‘static’
option ipaddr ‘127.0.0.1’
option netmask ‘255.0.0.0’

config interface ‘lan’
option ifname ‘eth0’
option type ‘bridge’
option proto ‘static’
option ipaddr ‘192.168.1.1’
option netmask ‘255.255.255.0’

config interface ‘wwan’
option proto ‘dhcp’

config interface ‘wlan’
option proto ‘static’
option ipaddr ‘192.168.2.1’
option netmask ‘255.255.255.0’

/etc/config/dhcp加上:
config dhcp lan
option interface lan
option ignore 1

config dhcp wan
option interface wan
option ignore 1

config dhcp wlan
option start ‘100’
option leasetime ‘12h’
option limit ‘150’
option interface ‘wlan’

/etc/config/firewall加上:
config zone
option name lan
option network ‘lan wlan’
option input ACCEPT
option output ACCEPT
option forward REJECT

config zone
option name wan
option network ‘wan wwan’
option input ACCEPT
option output ACCEPT
option forward ACCEPT
option masq 1
option mtu_fix 1

config forwarding
option src lan
option dest wan
从网上看到reset button复用的例子后,决定用reset按钮实现切换wifi。初步打算是这样的:


  • 按一下reset,切换客户端模式的配置(切换连接家里的路由还是连接公司的路由);

  • 按住reset 2~5秒,打开/关闭AP模式切换;

  • 按住reset 6秒以上,禁用所有客户端模式,重置为AP模式。

# cat /etc/hotplug2.rules
$include /etc/hotplug2-common.rules

SUBSYSTEM ~~ (^net$|^input$|^button$|^usb$|^ieee1394$|^block$|^atm$|^zaptel$|^tty$) {
exec /sbin/hotplug-call %SUBSYSTEM%
}

DEVICENAME == watchdog {
exec /sbin/watchdog -t 5 /dev/watchdog
next-event
}
可以看到hotplug已经监听button了,我们只用创建button对应的响应脚本就行了,在/etc/hotplug.d/button目录下创建的脚本会被自动执行

# mkdir -p /etc/hotplug.d/button

cd /etc/hotplug.d/button

vi buttons

#!/bin/sh
logger $BUTTON $ACTION
logger “”

保存退出

# logread -f
Sep 4 13:53:34 OpenWrt user.notice root: reset pressed
Sep 4 13:53:34 OpenWrt user.notice root:
Sep 4 13:53:34 OpenWrt user.notice root: reset released
Sep 4 13:53:34 OpenWrt user.notice root:

这时按一下reset,可以看到上面的log输出
 

通过system进行配置


首先创建如下脚本:

# cat /etc/hotplug.d/button/00-button

#!/bin/sh
. /lib/functions.sh
do_button () {
local button
local action
local handler
local min
local max

config_get button $1 button
config_get action $1 action
config_get handler $1 handler
config_get min $1 min
config_get max $1 max

[ "$ACTION" = "$action" -a "$BUTTON" = "$button" -a -n "$handler" ] && {
        [ -z "$min" -o -z "$max" ] && eval $handler
        [ -n "$min" -a -n "$max" ] && {
                [ $min -le $SEEN -a $max -ge $SEEN ] && eval $handler
        }
}

}

config_load system
config_foreach do_button button
该脚本会读取system配置,对所有的button配置部分调用相应的handler
system配置如下:

# cat /etc/config/system
config system
option hostname OpenWrt
option timezone UTC

config timeserver ntp
list server 0.openwrt.pool.ntp.org
list server 1.openwrt.pool.ntp.org
list server 2.openwrt.pool.ntp.org
list server 3.openwrt.pool.ntp.org
option enable_server 0

config button
option button reset
option action released
option handler “/opt/bin/toggle_wifi_client”
option min 0
option max 1

config button
option button reset
option action released
option handler “/opt/bin/toggle_ap”
option min 2
option max 5

config button
option button reset
option action released
option handler “/opt/bin/reset_to_ap”
option min 6
option max 20
可以看到, 按下reset按钮会调用toggle_wifi_client,按住reset 2~5秒调用toggle_ap,按住6秒以上调用reset_to_ap

# cat toggle_wifi_client

#!/bin/sh
logger toggle_wifi_client “<===================”

st=$(uci -q get wireless.home.disabled)
if [ “$st” == “1” ]; then
uci set wireless.company.disabled=1
uci set wireless.home.disabled=0
else
uci set wireless.home.disabled=1
uci set wireless.company.disabled=0
fi
/etc/init.d/network restart

# cat toggle_ap

#!/bin/sh
logger toggle_ap “<===================”

st=$(uci -q get wireless.ap.disabled)
if [ “$st” == “1” ]; then
uci set wireless.ap.disabled=0
else
uci set wireless.ap.disabled=1
fi
/etc/init.d/network restart
/etc/init.d/network restart

# cat reset_to_ap

#!/bin/sh
logger reset_to_ap “<===================”

uci set wireless.ap.disabled=0
uci set wireless.home.disabled=1
uci set wireless.company.disabled=1
/etc/init.d/network restart
以上配置+脚本全部准备好之后,wifi切换功能就ready了

看看系统配置,已经生效:

# uci show system
system.@system[0]=system
system.@system[0].hostname=OpenWrt
system.@system[0].timezone=UTC
system.ntp=timeserver
system.ntp.server=0.openwrt.pool.ntp.org 1.openwrt.pool.ntp.org 2.openwrt.pool.ntp.org 3.openwrt.pool.ntp.org
system.ntp.enable_server=0
system.@button[0]=button
system.@button[0].button=reset
system.@button[0].action=released
system.@button[0].handler=/opt/bin/toggle_wifi_client
system.@button[0].min=0
system.@button[0].max=1
system.@button[1]=button
system.@button[1].button=reset
system.@button[1].action=released
system.@button[1].handler=/opt/bin/toggle_ap
system.@button[1].min=2
system.@button[1].max=5
system.@button[2]=button
system.@button[2].button=reset
system.@button[2].action=released
system.@button[2].handler=/opt/bin/reset_to_ap
system.@button[2].min=6
system.@button[2].max=20

看看wireless配置:

# uci show wireless
wireless.radio0=wifi-device
wireless.radio0.type=mac80211
wireless.radio0.channel=11
wireless.radio0.macaddr=1c:fa:68:f9:f3:4a
wireless.radio0.hwmode=11ng
wireless.radio0.htmode=HT20
wireless.radio0.ht_capab=SHORT-GI-20 SHORT-GI-40 RX-STBC1 DSSS_CCK-40
wireless.ap=wifi-iface
wireless.ap.device=radio0
wireless.ap.network=wlan
wireless.ap.mode=ap
wireless.ap.ssid=OpenWrt
wireless.ap.encryption=none
wireless.ap.disabled=0
wireless.company=wifi-iface
wireless.company.network=wwan
wireless.company.ssid=company_ssid
wireless.company.encryption=psk2
wireless.company.device=radio0
wireless.company.mode=sta
wireless.company.bssid=00:13:10:41:69:EE
wireless.company.key=xxxxxxxx
wireless.company.disabled=0
wireless.home=wifi-iface
wireless.home.network=wwan
wireless.home.ssid=home_ssid
wireless.home.encryption=psk2
wireless.home.device=radio0
wireless.home.mode=sta
wireless.home.bssid=00:21:29:74:33:EB
wireless.home.key=xxxxxxxx
wireless.home.wds=1
wireless.home.disabled=1

可以看到ap模式开启,company配置开启,home配置关闭,与/etc/config/wireless中的配置一致

长按reset 2秒后松开,可以看到如下log:

Sep  4 13:53:34 OpenWrt user.notice root: reset pressed
Sep 4 13:53:34 OpenWrt user.notice root:
Sep 4 13:53:37 OpenWrt user.notice root: toggle_ap <===================
Sep 4 13:53:37 OpenWrt daemon.notice netifd: Interface ‘lan’ is now down
Sep 4 13:53:37 OpenWrt kern.info kernel: [ 186.810000] br-lan: port 1(eth0) entered disabled state
Sep 4 13:53:37 OpenWrt kern.info kernel: [ 186.810000] device eth0 left promiscuous mode
Sep 4 13:53:37 OpenWrt kern.info kernel: [ 186.810000] br-lan: port 1(eth0) entered disabled state
Sep 4 13:53:37 OpenWrt kern.info kernel: [ 186.830000] eth0: link down
Sep 4 13:53:37 OpenWrt daemon.notice netifd: Interface ‘loopback’ is now down
Sep 4 13:53:37 OpenWrt daemon.notice netifd: Interface ‘wlan’ is now down
Sep 4 13:53:37 OpenWrt daemon.notice netifd: wwan (1467): Sending select for 10.228.208.196…
Sep 4 13:53:37 OpenWrt daemon.notice netifd: wwan (1467): Received SIGTERM
Sep 4 13:53:37 OpenWrt daemon.notice netifd: Interface ‘wwan’ is now down
Sep 4 13:53:38 OpenWrt user.info firewall: removing lan (br-lan) from zone lan
Sep 4 13:53:39 OpenWrt kern.info kernel: [ 188.950000] device eth0 entered promiscuous mode
Sep 4 13:53:39 OpenWrt daemon.notice netifd: Interface ‘lan’ is now up
Sep 4 13:53:39 OpenWrt daemon.notice netifd: Interface ‘loopback’ is now up
Sep 4 13:53:40 OpenWrt daemon.warn dnsmasq-dhcp[1893]: DHCP packet received on wlan0-1 which has no address
Sep 4 13:53:40 OpenWrt kern.info kernel: [ 189.700000] eth0: link up (100Mbps/Full duplex)
Sep 4 13:53:40 OpenWrt kern.info kernel: [ 189.700000] br-lan: port 1(eth0) entered forwarding state
Sep 4 13:53:40 OpenWrt kern.info kernel: [ 189.710000] br-lan: port 1(eth0) entered forwarding state
Sep 4 13:53:40 OpenWrt user.notice ifup: Enabling Router Solicitations on lan (br-lan)
Sep 4 13:53:41 OpenWrt user.info firewall: adding lan (br-lan) to zone lan
Sep 4 13:53:42 OpenWrt kern.info kernel: [ 191.710000] br-lan: port 1(eth0) entered forwarding state
Sep 4 13:53:42 OpenWrt user.notice ifup: Enabling Router Solicitations on loopback (lo)
Sep 4 13:53:44 OpenWrt kern.info kernel: [ 193.400000] wlan0-1: deauthenticating from 00:13:10:41:69:ee by local choice (reason=3)
Sep 4 13:53:46 OpenWrt daemon.notice netifd: Interface ‘lan’ is now down
Sep 4 13:53:46 OpenWrt kern.info kernel: [ 195.710000] br-lan: port 1(eth0) entered disabled state
Sep 4 13:53:46 OpenWrt kern.info kernel: [ 195.740000] wlan0: authenticate with 00:13:10:41:69:ee
Sep 4 13:53:46 OpenWrt kern.info kernel: [ 195.750000] wlan0: send auth to 00:13:10:41:69:ee (try 1/3)
Sep 4 13:53:46 OpenWrt kern.info kernel: [ 195.750000] device eth0 left promiscuous mode
Sep 4 13:53:46 OpenWrt kern.info kernel: [ 195.760000] br-lan: port 1(eth0) entered disabled state
Sep 4 13:53:46 OpenWrt kern.info kernel: [ 195.760000] wlan0: authenticated
Sep 4 13:53:46 OpenWrt kern.info kernel: [ 195.780000] eth0: link down
Sep 4 13:53:46 OpenWrt kern.info kernel: [ 195.790000] wlan0: associate with 00:13:10:41:69:ee (try 1/3)
Sep 4 13:53:46 OpenWrt kern.info kernel: [ 195.800000] wlan0: RX AssocResp from 00:13:10:41:69:ee (capab=0x411 status=0 aid=9)
Sep 4 13:53:46 OpenWrt kern.info kernel: [ 195.800000] wlan0: associated
Sep 4 13:53:46 OpenWrt daemon.notice netifd: Interface ‘loopback’ is now down
Sep 4 13:53:46 OpenWrt daemon.notice netifd: Interface ‘wwan’ is now down
Sep 4 13:53:47 OpenWrt user.info firewall: removing lan (br-lan) from zone lan
Sep 4 13:53:48 OpenWrt kern.info kernel: [ 197.950000] device eth0 entered promiscuous mode
Sep 4 13:53:48 OpenWrt daemon.notice netifd: Interface ‘lan’ is now up
Sep 4 13:53:48 OpenWrt daemon.notice netifd: Interface ‘loopback’ is now up
Sep 4 13:53:49 OpenWrt user.notice ifup: Enabling Router Solicitations on lan (br-lan)
Sep 4 13:53:49 OpenWrt kern.info kernel: [ 198.700000] eth0: link up (100Mbps/Full duplex)
Sep 4 13:53:49 OpenWrt kern.info kernel: [ 198.700000] br-lan: port 1(eth0) entered forwarding state
Sep 4 13:53:49 OpenWrt kern.info kernel: [ 198.710000] br-lan: port 1(eth0) entered forwarding state
Sep 4 13:53:50 OpenWrt user.info firewall: adding lan (br-lan) to zone lan
Sep 4 13:53:51 OpenWrt kern.info kernel: [ 200.710000] br-lan: port 1(eth0) entered forwarding state
Sep 4 13:53:51 OpenWrt user.notice ifup: Enabling Router Solicitations on loopback (lo)
Sep 4 13:53:53 OpenWrt kern.info kernel: [ 202.350000] wlan0: deauthenticating from 00:13:10:41:69:ee by local choice (reason=3)
Sep 4 13:53:55 OpenWrt user.notice root: reset released
Sep 4 13:53:55 OpenWrt user.notice root:
Sep 4 13:53:55 OpenWrt kern.info kernel: [ 204.660000] wlan0: authenticate with 00:13:10:41:69:ee
Sep 4 13:53:55 OpenWrt kern.info kernel: [ 204.670000] wlan0: send auth to 00:13:10:41:69:ee (try 1/3)
Sep 4 13:53:55 OpenWrt daemon.notice netifd: wwan (3065): udhcpc (v1.19.4) started
Sep 4 13:53:55 OpenWrt daemon.notice netifd: wwan (3065): Sending discover…
Sep 4 13:53:55 OpenWrt kern.info kernel: [ 204.880000] wlan0: send auth to 00:13:10:41:69:ee (try 2/3)
Sep 4 13:53:55 OpenWrt kern.info kernel: [ 204.880000] wlan0: authenticated
Sep 4 13:53:55 OpenWrt kern.info kernel: [ 204.910000] wlan0: associate with 00:13:10:41:69:ee (try 1/3)
Sep 4 13:53:55 OpenWrt kern.info kernel: [ 205.120000] wlan0: associate with 00:13:10:41:69:ee (try 2/3)
Sep 4 13:53:55 OpenWrt kern.info kernel: [ 205.150000] wlan0: RX AssocResp from 00:13:10:41:69:ee (capab=0x411 status=0 aid=9)
Sep 4 13:53:55 OpenWrt kern.info kernel: [ 205.160000] wlan0: associated
Sep 4 13:53:58 OpenWrt daemon.notice netifd: wwan (3065): Sending discover…
Sep 4 13:54:01 OpenWrt daemon.notice netifd: wwan (3065): Sending discover…
Sep 4 13:54:04 OpenWrt daemon.notice netifd: wwan (3065): Sending select for 10.228.208.194…
Sep 4 13:54:04 OpenWrt daemon.notice netifd: wwan (3065): Lease of 10.228.208.194 obtained, lease time 86400
Sep 4 13:54:04 OpenWrt daemon.notice netifd: Interface ‘wwan’ is now up
Sep 4 13:54:05 OpenWrt user.notice ifup: Allowing Router Advertisements on wwan (wlan0)
Sep 4 13:54:06 OpenWrt user.info firewall: adding wwan (wlan0) to zone wan
Sep 4 13:54:11 OpenWrt daemon.info dnsmasq[1893]: reading /tmp/resolv.conf.auto
Sep 4 13:54:11 OpenWrt daemon.info dnsmasq[1893]: using nameserver 192.168.100.10#53
Sep 4 13:54:11 OpenWrt daemon.info dnsmasq[1893]: using nameserver 192.168.100.11#53
Sep 4 13:54:11 OpenWrt daemon.info dnsmasq[1893]: using nameserver 202.106.0.20#53
Sep 4 13:54:11 OpenWrt daemon.info dnsmasq[1893]: using local addresses only for domain lan

可以看到toggle_ap <===================,toggle_ap脚本被执行

# uci show wireless
wireless.radio0=wifi-device
wireless.radio0.type=mac80211
wireless.radio0.channel=11
wireless.radio0.macaddr=1c:fa:68:f9:f3:4a
wireless.radio0.hwmode=11ng
wireless.radio0.htmode=HT20
wireless.radio0.ht_capab=SHORT-GI-20 SHORT-GI-40 RX-STBC1 DSSS_CCK-40
wireless.ap=wifi-iface
wireless.ap.device=radio0
wireless.ap.network=wlan
wireless.ap.mode=ap
wireless.ap.ssid=OpenWrt
wireless.ap.encryption=none
wireless.ap.disabled=1
wireless.company=wifi-iface
wireless.company.network=wwan
wireless.company.ssid=company_ssid
wireless.company.encryption=psk2
wireless.company.device=radio0
wireless.company.mode=sta
wireless.company.bssid=00:13:10:41:69:EE
wireless.company.key=xxxxxxxx
wireless.company.disabled=0
wireless.home=wifi-iface
wireless.home.network=wwan
wireless.home.ssid=home_ssid
wireless.home.encryption=psk2
wireless.home.device=radio0
wireless.home.mode=sta
wireless.home.bssid=00:21:29:74:33:EB
wireless.home.key=xxxxxxxx
wireless.home.wds=1
wireless.home.disabled=1

可以看到AP模式被禁用了,wireless.ap.disabled=1

reset按钮功能扩展完成,昨晚在家里试验,按了一下reset按钮,成功切换连接到家里的主无线路由,并且AP模式也正常工作。今天早上在公司试验,开启路由默认就连接上公司路由,不过长按2秒后关闭AP模式时系统挂了(自动重启了),ssh半天连不上,重试后正常了,还是有些不稳定