Obsługa przycisków w OpenWrt
Ostatnia zmiana: 2015-09-22 07:38

Większość ruterów posiada jakieś przyciski. Zwykle jest dostępny "Reset" (lub "Restore"), czasami także pojawia się przycisk oznaczony WPS, SES czy QSS. Ze względów oszczędnościowo-praktycznych, fizycznie taki przycisk zwykle jest bezpośrednio podłączony pod jedną z linii wejściowych CPU rutera (zwanych GPIO) i tym samym jest dostępny do programowego obsłużenia. Ponieważ zwykle OpenWrt zawiera obsługę przycisków dla danej platformy, możemy to wykorzystać do własnych celów np. odmontowania dysku USB, zatrzymania pracy programu do pobierania torrentów, wyłączenie/przełączenia wifi, resetu (!) czy setki innych pomysłów które chcemy zrealizować.

Nazwy przycisków

Same moduły do obsługi powinny być już zawarte w systemie (najczęściej jest to realizowane przez pakiet kmod-button-hotplug) więc nie ma już potrzeby ich instalacji. Sama obsługa jest zrealizowana przez podsystem hotplug - czyli jeżeli naciśniemy przycisk to zostaną wykonane wszystkie programy zawarte w pewnym katalogu; w przypadku OpenWrt jest to /etc/hotplug.d/button. Zostaną one uruchomione zarówno po naciśnięciu jak i zwolnieniu przycisków. Do skryptów przekazywane są zmienne środowiskowe zawierające informacje o nazwie wciśniętego przycisku (zmienna $BUTTON), akcji (zmienna $ACTION) oraz czasie od ostatniego naciśnięcia przycisku (zmienna $SEEN).

Ponieważ w zależności od typu rutera przyciski mogą się różnie nazywać, najpierw należy sprawdzić pod jak nazwą są widoczne. Najprościej umieścić w w/w katalogu prosty skrypt który wypisze nam to samodzielnie:


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

a w nim umieścić następującą zawartość


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

Zapisujemy zmiany i po kolei należy kilkukrotnie nacisnąć wszystkie przyciski. Po wykonaniu polecania logread powinny pojawić się komunikaty typu


    Jan  1 00:01:15 OpenWrt user.notice root: BTN_1
    Jan  1 00:01:15 OpenWrt user.notice root: pressed
    Jan  1 00:01:16 OpenWrt user.notice root: BTN_1
    Jan  1 00:01:16 OpenWrt user.notice root: released

A to oznacza że naciśnięty przycisk nazywa się BTN_1. W zależności od typu rutera możemy tam znaleźć napisy typu "reset", "wps", "ses" itp.

Skrypt do obsługi przycisków

Skoro wiemy już jak się nazywa dany przycisk - obsługa sprowadza się do napisania odpowiedniego skryptu. Czyli w katalogu /etc/hotplug.d/button należy utworzyć plik o dowolnej nazwie, np. 00-button


    # mkdir -p /etc/hotplug.d/button
    # cd /etc/hotplug.d/button
    # touch 00-button

a w nim umieścić np. taki kod:


    if [ "$ACTION" = "pressed" ]; then
        if [ "$BUTTON" = "BTN_0" ]; then
            polecenia do wykonania po naciśnięciu przyciku BTN_0
        elif [ "$BUTTON" = "BTN_1" ]; then
            polecenia do wykonania po naciśnięciu przyciku BTN_1
        fi
    fi

Praktycznie zastosowanie - skrypt do włączenia/wyłączenia wifi po naciśnięciu przycisku o nazwie "ses" dostępny jest tutaj.

Obsługa przycisków przy pomocy UCI

Każdorazowe modyfikowanie skryptu może być uciążliwe. Można zrobić uniwersalną obsługę przycisków przy pomocy standardu w OpenWrt - UCI, definiując odpowiednią sekcję w plikach konfiguracyjnych. Taki skrypt jest gotowy i wystarczy go pobrać od deweloperów OpenWrt:


    # mkdir -p /etc/hotplug.d/button
    # wget -O /etc/hotplug.d/button/00-button http://dev.openwrt.org/export/21216/trunk/target/linux/atheros/base-files/etc/hotplug.d/button/00-button

(w moich obrazach AA ten skrypt jest już dodany)
Cała obsługa przycisków sprowadza się do umieszczenia odpowiedniej sekcji w pliku /etc/config/system. W przykładzie - wyłączenie wifi (tylko wyłączenie) po naciśnięciu przycisku "WPS"


    # uci add system button
    # uci set system.@button[-1].button=wps
    # uci set system.@button[-1].action=pressed
    # uci set system.@button[-1].handler='uci set wireless.@wifi-device[0].disabled=1 && wifi'
    # uci commit system

Dostępne opcje to:

  • button - nazwa przycisku
  • action - pressed lub released, czyli akcja będzie wykonana po wciśnięciu lub puszczeniu przycisku
  • handler - nazwa skryptu/polecenie do wykonania
Ten skrypt umożliwia także zliczanie czasu naciśnięcia i tym samym wykonanie różnej akcji po przytrzymaniu przycisku np. 3s lub 10s. Aby to wykonać akcja powinna być zdefiniowana jako "released" oraz należy ustawić opcje "min" oraz "max" - to czas podany w sekundach. Czyli np.


    # uci add system button
    # uci set system.@button[-1].button=BTN_1
    # uci set system.@button[-1].action=released
    # uci set system.@button[-1].handler='logger czas nacisniecia: 0-3s'
    # uci set system.@button[-1].min=0
    # uci set system.@button[-1].max=3
    # uci add system button
    # uci set system.@button[-1].button=BTN_1
    # uci set system.@button[-1].action=released
    # uci set system.@button[-1].handler='logger czas nacisniecia: 8-10s'
    # uci set system.@button[-1].min=8
    # uci set system.@button[-1].max=10
    # uci commit system

Jeżeli teraz naciśniemy przycisk BTN_1 i przytrzymamy go do 3s lub 8-10 to w logach (logread) powinna pojawić się odpowiednia informacja o tym. Dzięki temu można zrealizować różną funkcjonalność obsługiwaną przez jednej przycisk, np. trzymamy do 2s - wyłącza się wifi, trzymamy do 10s - odmontowywuje dyski, powyżej 30s - robi reset systemu.

Przykład: odmontowanie dysków po naciśnięciu przycisku


    # uci add system button
    # uci set system.@button[-1].button=BTN_1
    # uci set system.@button[-1].action=released
    # uci set system.@button[-1].handler='for i in $(mount | awk '/dev\/sd[a-z]/ { print $1}'); do umount $i; done'
    # uci set system.@button[-1].min=5
    # uci set system.@button[-1].max=10
    # uci commit system

Barrier Breaker i późniejsze

Powyższe elementy są też prawdziwe dla Barrier Breaker i późniejszych wydań. Jednakże system BB zawiera już predefiniowaną obsługę przycisków, umiejscowioną w katalogu /etc/rc.button. Zawarte tam skrypty nazywają się tak samo jak przyciski - naciśniecie np. reset powoduje wykonanie skryptu /etc/rc.button/reset, przekazując wszystkie zmienne - $SEEN, $BUTTON, $ACTION. Zdefiniowane są domyślnie skrypty o nazwach:
- reset: naciśnięcie do 1s powoduje restart urządzenia, powyżej 5s - przywrócenie ustawień domyślnych (firstboot)
- power: wyłączenie urządzenia
- rfkill: wyłączenie interfejsu radiowego
Po dodaniu pakietu hostapd-utils pojawi się także obsługa przycisku wps.

Przed wykonaniem własnych skryptów należy więc pamiętać że mogą się wykonać także skrypty z tego katalogu. Można też oczywiście w tym katalogu umieścić własne skrypty pod odpowiednimi nazwami. W przykładach znajduje się skrypt rfkill przełączający radio. Jeżeli chcemy taką funkcjonalność podpiąć pod przycisk wps obecny np. w niektórych routerach TP-LINK wystarczy zrobić plik /etc/rc.button/wps i umieścić w nim odpowiedni kod. Lub prościej - zrobić dowiązanie symboliczne do rfkill czyli:


    # ln -s /etc/rc.button/rfkill /etc/rc.button/wps

Po naciśnięciu przycisku wps zostanie przełączony interfejs radiowy. Niektóre routery mogę posiadać przycisk który jest nazwany np. wps a nie reset - więc przez zdaniem pytania "dlaczego nie działa" warto sprawdzić pod jaką nazwą widoczny jest przycisk - patrz na górze tego poradnika.