OpenWRT自定義機身按鍵功能教學:爲WR30U添加WIFI開關按鍵

小米WR30U上面有個“Mesh”按鈕,但是刷了 OpenWRT的 Ups-WR30U 這個按鈕有什麼用呢?答案是:你想怎麼用就怎麼用!OpenWRT中按鈕的功能是可以自定義的!本文就和你分享OpenWRT自定義機身按鍵功能的方法,可以說是發揮 OpenWRT 強大客製化自由度的典範。

題外話:在搜集資料的時候竟然找到自己10年前的文章:OpenWRT、dd-wrt自設定路由按鈕功能,而且我完全忘了自己寫過。。。看裡面的內容,嗯,我這十年是有進步的。

OpenWRT自定義按鍵功能的思路

在OpenWRT中自定義按鍵功能的思路有兩種:

路由器按鍵類型客製化功能方法
已預設的按鈕
例如 RESET
修改已有的 /etc/rc.button/ 中的代碼
未使用的按鈕
例如 MESH
定義按鈕並添加腳本代碼

Ups-WR30U的「Mesh」就屬於第二種按鈕,根據官網的WIKI:[OpenWrt Wiki] Attach functions to a push button,爲這個按鈕定義按鍵功能需要兩個步驟:

  • 找到按鈕的編號
  • 定義按鈕的功能

必須掌握的OpenWRT工具

本文有兩個工具/技能是必須要學的,第一是 命令行操作 OpenWRT,可以透過 Ups-WR30 已預裝的 Terminal 功能,在 192.168.0.1 的控制後臺選 Services -> Terminal

還有就是要會修改 OpenWRT 系統裡面文件,建議使用WinSCP這個免費軟件 WinSCP :: Official Site :: Download

File Protocol 是 SCP ; Host name 輸入 192.168.0.1 ; 端口 22 ; username是root
這樣就很容易修改腳本文件了

找到OpenWRT按鈕編號的方法

如果你是使用WR30U就不用再找按鈕編號了,網上已經有資料提示了「Mesh」的號碼是 BTN-9 。你可以直接跳到下一段。

如果不知道按鍵號碼,請岸OpenWRT的WIKI教在 SSH 或 Terminal 運行這段代碼:

# 安裝插件
opkg update
opkg install kmod-button-hotplug

# 新建目錄 
mkdir -p /etc/hotplug.d/button
 
# 寫入以下內容到 /etc/hotplug.d/button/buttons 文件,直至遇到"EOF"停止
cat << "EOF" > /etc/hotplug.d/button/buttons
logger "the button was ${BUTTON} and the action was ${ACTION}"
EOF

這個代碼分成三個部分:

  1. 安裝 kmod-button-hotplug 插件
  2. 創建一個叫 button的目錄
  3. 寫入 logger命令串 爲button文件的內容,讓系統記錄按鍵時候的動作

完成後,在 SSH 或 Terminal 輸入 logread 會看到:

Jan 1 00:01:15 OpenWrt user.notice root: the button was BTN_9 and the action was pressed

就能找到對應的 BTN_X 號碼和動作(pressed/released)。

必須是適配的OpenWRT中有對硬件按鈕定義,我們才能在OpenWRT中調用這個按鈕。通常用型號特定的OpenWRT版本會有定義,而”通用版“的OpenWRT就未必有硬件按鈕的定義。

OpenWRT自定義按鍵功能

找到了按鍵編號,要給他安排按鍵功能的方法,按照WIKI在 SSH 或 Terminal 運行這段代碼:

cat << "EOF" > /etc/hotplug.d/button/00-button
source /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
EOF
 
uci add system button
uci set system.@button[-1].button="BTN_9"
uci set system.@button[-1].action="pressed"
uci set system.@button[-1].handler="logger this is a BTN_9 pressed handler command"
uci commit system 

這段代碼的分兩個部分:

  1. 創建一個 00-button 的腳本,裡面定義了按鈕的動作,包括按下、鬆開、以及”長按秒數“
  2. 通過 uci 命令給系統添加按鍵(BTN_9)和對應的動作(pressed)和功能(logger BTN_9 pressed)
凡事你在本文看到 cat << … 一大段的命令,其實都是透過命令行形式、在指定目錄來創建文件,你也可以用WinSCP來手動創建文件並把代碼複製進去。後續用WinSCP來修改文件比起命令行方便一萬倍。

這樣操作後,你再用logread 應該能看到:

Jan 1 00:01:15 OpenWrt user.notice root: this is a BTN_9 pressed handler command

下面,我們只需要修改 uci set system.@button[-1].handler= 這句的命令,就能讓 BTN_9 按下去執行我們需要的功能。

Mesh按鈕變WIFI開關

OpenWRT中只需要在 SSH 或 Terminal 運行這段代碼輸入一句命令: wifi down ,WIFI信號就會關閉。所以我們可以嘗試:

uci set system.@button[-1].handler="wifi down"
uci commit system

這時候你按一下WR30U上的「Mesh」,WIFI信號就會關閉。成功的話就說明腳本已經生效。

但如何開WIFI呢?我們可以定義”長按“(3秒以上)爲打開WIFI (wifi up)在 SSH 或 Terminal 運行這段代碼:

uci add system button
uci set system.@button[-1].button="BTN_9"
uci set system.@button[-1].action="released"
uci set system.@button[-1].handler="wifi up"
uci set system.@button[-1].min="3"
uci set system.@button[-1].max="10"
uci commit system

這樣子你就有了一個按一下關WIFI,長按開WIFI的「Mesh」按鈕!

OpenWRT不僅支持按鍵執行單句命令,還可以執行腳本,這樣子就可以加入判斷語句,讓你只需要按一下就能「切換」WIFI的開關,不需要記住是長按還是短按,在 SSH 或 Terminal 運行這段代碼:

uci add system button
uci set system.@button[-1].button="BTN_9"
uci set system.@button[-1].action="released"
uci set system.@button[-1].handler="/usr/bin/wifionoff"
uci set system.@button[-1].min="0"
uci set system.@button[-1].max="3"
uci commit system

cat << "EOF" > /usr/bin/wifionoff
#!/bin/sh
STATEFILE="/tmp/wifionoff.state"
 
if [ "${#}" -eq 1 ]; then
    case "${1}" in
        "up"|"on") GOAL="on" ;;
        "down"|"off") GOAL="off" ;;
    esac
else
    if [ -e "${STATEFILE}" ]; then
	GOAL="on"
    else
        # if the statefile doesn't exist, turn wifi off
        GOAL="off"
    fi
fi
 
if [ "${GOAL}" = "off" ]; then
    /sbin/wifi down
    touch "${STATEFILE}"
else
    /sbin/wifi up
    # file may not exist if we're given args
    rm "${STATEFILE}" 2> /dev/null || true
fi
EOF
chmod u+x /usr/bin/wifionoff

這段代碼的意思是:

  • 按下BTN_9的時候執行 /usr/bin/wifionoff
  • 寫入代碼到 /usr/bin/wifionoff

[OpenWrt Wiki] 上還有好幾個開關WIFI的腳本,使用上文這個 wifi up 和 wifi down 而不是 wireless.radio.disable 的原因是他重啓之後會恢復到有WIFI的狀態,而 wireless.radio.disable 重啓只有不會自動開啓wifi (如果之前已經關閉)。

Mesh按鈕變2.4G WIFI開關

因爲小U家的無線設備都支援5Ghz WIFI,只有部Brother Laser Printer只支援2.4Ghz WIFI,所以我家的2.4Ghz是長期關閉,避免無謂的WIFI輻射,只有在要打印時候才會開2.4Ghz WIFI。那麼正好WR30U上面的這個按鈕就設定爲2.4Ghz WIFI的開關吧!

但是要單獨控制2.4Ghz WIFI用 wifi radio0 up / down 這個命令有時候會影響到 5Ghz,不知道爲什麼,所以經過研究,小U自己寫了以下的腳本,而且可以和luci網頁界面的聯動,不會出現按鈕生效了但是luci頁面不同步、控制不了的問題(因爲luci的enable/disable是同時控制 device和interface)。按鈕腳本如下:

#!/bin/sh

ISTATUS="$(uci -q get wireless.default_radio0.disabled)"
DSTATUS="$(uci -q get wireless.radio0.disabled)"

if [ "${ISTATUS}" = "1" ] && [ "${DSTATUS}" = "1" ]; then
	uci del wireless.default_radio0.disabled
	uci del wireless.radio0.disabled
        wifi reload
else
	uci set wireless.default_radio0.disabled='1' 
	uci set wireless.radio0.disabled='1'
	wifi reload
fi

EOF

因爲使用了wireless.xxx.disabled,所以需要加一個重啓時候確保2.4G WIFI狀態的boot/init script,這個script是放在 /etc/init.d/目錄。並且通過 /etc/init.d/xxx enable 來實現啓動自動執行 :

#!/bin/sh /etc/rc.common
# Example script
# Copyright (C) 2007 OpenWrt.org
 
START=100
STOP=15
 
start() {        
        echo start
	uci set wireless.default_radio0.disabled='1' 
	uci set wireless.radio0.disabled='1'
	wifi reload

}                 
 
stop() {          
        echo stop
        # commands to kill application 
}

但是一測試,怎麼不行?開機了2.4G WIFI依然“健在”?原來Init.d的腳本是在啓動過程中進行(也就是在WIFI啓動之前)所以不能用在init.d,而是要加在 /etc/rc.local 中。修改 /etc/rc.local :

# Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.
logger start rc local
/etc/wifi2goffdelay

exit 0

然後將 /etc/wifi2goffdelay 改爲:

logger wait 60s to disable 2.4g wifi
sleep 60
uci set wireless.default_radio0.disabled='1' 
uci set wireless.radio0.disabled='1'
wifi reload
logger 2.4g wifi is disable

我加入了logger來追蹤腳本運行的情況,可以在 System log中看到記錄:

到此你應該感受到,OpenWRT是允許你添加任何命令、任何想法到這個小小的按鈕上。甚至如果你嫌按鈕不夠,還能夠定義外接鍵盤的功能!有誰能想到有什麼實際應用例子呢?

結尾:

本文是小U的「玩開源、從OpenWRT開始」系列文章的其中一篇。自從Ups-WR30U開源路由器得到大家的熱烈支持,小U也收到了客戶的各種使用OpenWRT的問題查詢,順勢就着手把大家會遇到的,想要用的,都集結成這個系列的文章,希望讓各位從OpenWRT體驗和玩樂開源系統。不需要靠AI,你就能讓路由器變得更”聰明“!

如果你還未有OpenWRT路由器,不妨從 Ups-WR30U 上手吧:

歡迎你的留言討論:

你可以一針見血

by Upsangel
Logo