Benutzer-Werkzeuge

Webseiten-Werkzeuge


bastelprojekte:menuconfig

Ein Script, das die Konfiguration eines Routers per ssh erlaubt, und die ganzen uci Kommandos in einem Text-GUI verpackt. Ähnlich dem Web-Konfigurator - letzterer ist aber nur verfügbar, wenn man direkt am Gerät sitzt.

Man muss sich auf seinem lokalem Linux-Rechner das Paket 'dialog' installieren (apt-get install dialog oder ähnliches). Dann aufrufen mit der IPV6-Adresse des zu konfigurierenden Routers:

./menuconfig.sh aaa.bbbb.cccc.dddd.eeee.ffff.gggg.hhhh

Ich werde das Script von Zeit zu Zeit hier im Wiki aktualisieren. Letzter Stand 2020-06-17 (oder in der History nachsehen).

#!/bin/sh
# -*- tab-width:4; indent-tabs-mode: nil; -*-

################################################################################
# A 'make menuconfig' style script to provide a simple UI for configuring
# a Freifunk node.
# It is based on the tool 'dialog' which is also used in the kernel's 
# make menuconfig.
#
# Documentation:
#   man dialog
#   https://invisible-island.net/dialog/manpage/dialog.html (Authors site)
#
# Online access to the sources and examples:
#   https://fossies.org/linux/misc/dialog-1.3-20190211.tgz/
#
# Gluon command line documentation (uci commands):
#   https://github.com/freifunk-gluon/gluon/wiki/Commandline-administration
# 
# Author:
#   Alexander Lehner - 2019 - freifunk@edv-buero-lehner.de
#   Public Domain license
################################################################################

##########
# The script's syntax is based on 'ash' which comes along with busybox.
# We can run it with bash and dash. But not /bin/sh, if /bin/sh is the
# regular POSIX shell (rarely installed at all).
# So, first of all we have to get rid of '/bin/sh' as interpreter.
# https://wiki.ubuntu.com/DashAsBinSh
#
# Most compatibility issues arose with following:
# One may not type 
# function foo() 
# {
# ...
#
# instead use
# foo() {
# ...
#
# if [ $x == $y ]
# The '==' must be replaced by '='
#
# read
# alone does not work, it lacks the variable name parameter. Instead:
# read x

##########
# Determine which shell we are using.
# Some distros have 
# /bin/sh -> /bin/bash
# or 
# /bin/sh -> /bin/busybox
#
# https://unix.stackexchange.com/questions/71121/determine-shell-in-script-during-runtime

if [ `readlink /proc/$$/exe` = "/bin/sh" ]; then
    if [ -x /bin/bash ]; then
        echo "Seems to use /bin/sh, escaping to to /bin/bash".
        /bin/bash $0 "$@"
    elif [ -x /bin/dash ]; then
        echo "Seems to use /bin/sh, escaping to to /bin/dash".
        /bin/dash $0 "$@"
    elif [ -x /bin/ash ]; then
        echo "Seems to use /bin/sh, escaping to to /bin/ash".
        /bin/ash $0 "$@"
    else
        echo "No suitable shell (ash, dash, bash) found - exiting."
        exit 2
    fi
    exit $?
fi

#
# The main entry point is the function ffm_mainmenu() below.
# 


##########
# 'dialog'
# Has a strange arrangement of IO handles and redirections around its calls,
# as well as a rather complicated RESULT and retval handling.
# Refer to the ffm_mainmenu function, where all those details are explained.
#

################################################################################
# As long as we cannot run this script locally on a FF node, it is 
# necessary to exchange data via ssh.
# Give the IPV6 address as command line argument $1. 
# These variables are initialized in the main entry point
# at the very bottom of this file.

g_node_ip=""


################################################################################
# Use ff_sshcmde [<args ....>]
# to echo the commandline to stdout.
# This is the preferred way for all set-routines.
################################################################################
ff_sshcmde() {
    echo "$@"
    # -x: no X11 redirection
    ssh -x -l root $g_node_ip "$@"
}

################################################################################
# Execute the parameters via ssh as above.
# Do not print the commandline to stdout, because the stdout might be 
# interpreted by the caller.
# If the subcommand (what is executed inside ssh) fails, print the
# command line to stderr for diagnosis.
################################################################################
ff_sshcmd() {
    # -x: no X11 redirection
    ssh -x -l root $g_node_ip "$@"
    # The code below will destroy the precious return code in $?.
    RESULT=$?
    if [ $RESULT != 0 ]; then
        echo "Error in: $@" 1>&2
    fi
    return $RESULT
}

################################################################################
# Get/Set the hostname
# Returns: single-word string
################################################################################
ff_pretty_hostname() {
    if [ -z "$1" ]; then
        # No argument - retrieve value
        ff_sshcmd pretty-hostname
    else
        # Set value
        ff_sshcmde pretty-hostname "$@"
    fi
}


################################################################################
# Get/Set contact email address
################################################################################
ff_contact() {
    if [ -z "$1" ]; then
        # No argument - retrieve value
        ff_sshcmd uci get gluon-node-info.@owner[0].contact
    else
        # Set value
        ff_sshcmde uci add gluon-node-info owner
        ff_sshcmde uci set gluon-node-info.@owner[0].contact="$@"
        ff_sshcmde uci commit gluon-node-info
    fi
}

################################################################################
# Get the Model Name of the device. No Set functionality.
# Returns: multi-word string
################################################################################
ff_sys_model() {
    ff_sshcmd cat /tmp/sysinfo/model
}


################################################################################
# Returns list of LAN interfaces
################################################################################
ff_sys_lan_ifnames() {
    ff_sshcmd cat /lib/gluon/core/sysconfig/lan_ifname
}


################################################################################
# Returns a list of interfaces which act as a PC client port for internet access
################################################################################
ff_client_interfaces() {
    ff_sshcmd uci get network.client.ifname
}


################################################################################
# Get/Set the state of the autoupdater
# Values: 0 or 1
################################################################################
ff_autoupdate_enabled() {
    if [ -z "$1" ]; then
        # No argument - retrieve value
        # If key is not found, assume '1' as default
        ff_sshcmd uci get autoupdater.settings.enabled || echo 1
    else

        # Set value
        ff_sshcmde uci set autoupdater.settings.enabled=$1
        ff_sshcmde uci commit autoupdater
        ff_sshcmde autoupdater -f
    fi
}


################################################################################
# Get/Set the branch name of the autoupdater
################################################################################
ff_autoupdate_branch() {
    if [ -z "$1" ]; then
        # No argument - retrieve value
        # If key is not found, assume 'stable' as default
        ff_sshcmd uci get autoupdater.settings.branch || echo "stable"
    else

        # Set value
        ff_sshcmde uci set autoupdater.settings.branch=$1
        ff_sshcmde uci commit autoupdater
        ff_sshcmde autoupdater -f
    fi
}


################################################################################
# Get/Set the 'share location' property
# Returns '1' or '0' or probably even '' (if this is supported by uci).
# We don't convert empty strings to '0' here.
################################################################################
ff_share_location() {
    if [ -z "$1" ]; then
        # No argument - retrieve value
        # If key is not found, assume '1' as default
        ff_sshcmd uci get gluon-node-info.@location[0].share_location || echo 1
    else

        # Set Value
        ff_sshcmde uci set gluon-node-info.@location[0].share_location=$1
        ff_sshcmde uci commit gluon-node-info
    fi
}


################################################################################
# Get/Set the 'Mesh On WAN' property via UCI
# Values: 0 or 1
################################################################################
ff_mesh_wan_disabled() {
    if [ -z "$1" ]; then
        # No argument - retrieve value

        # If key is not found, assume '1' as default
        ff_sshcmd uci get network.mesh_wan.disabled || echo 1
    else
        # Set new value.
        ff_sshcmde uci set network.mesh_wan.disabled=$1
        ff_sshcmde uci commit network
    fi
}

################################################################################
# Get/Set the 'Mesh On LAN' property via UCI
# Values: 0 or 1
################################################################################
ff_mesh_lan_disabled() {
    if [ -z "$1" ]; then
        # No argument - retrieve value

        # If key is not found, assume '1' as default

        ff_sshcmd uci get network.mesh_lan.disabled || echo 1
    else
        # Set new value.
        ff_sshcmde uci set network.mesh_lan.disabled=$1
        ff_sshcmde uci commit network

        if [ "$1" = "0" ]; then
            # Activate:
            for ifname in $g_sys_lan_ifnames; do
                ff_sshcmde uci del_list network.client.ifname=$ifname
            done
        else
            # Deactivate:
            for ifname in $g_sys_lan_ifnames; do
                ff_sshcmde uci add_list network.client.ifname=$ifname
            done
            ff_sshcmde uci commit network
        fi
    fi
}


################################################################################
# Get/Set the Mesh-VPN option
# Values: 0 or 1
################################################################################
ff_mesh_vpn_enabled() {
    if [ -z "$1" ]; then

        # No argument - retrieve value
        # If key is not found, assume '1' as default
        ff_sshcmd uci get fastd.mesh_vpn.enabled || echo 1

    else

        # Set new value.
        if [ "$1" = "0" ]; then
            # Disable
            # Note: "/etc/init.d/fastd stop" won't stop fastd process if enabled=0.
            ff_sshcmde /etc/init.d/fastd stop
            ff_sshcmde uci set fastd.mesh_vpn.enabled=0
            ff_sshcmde uci commit fastd
        else
            # Enable
            ff_sshcmde uci set fastd.mesh_vpn.enabled=1
            ff_sshcmde uci commit fastd
            ff_sshcmde /etc/init.d/fastd generate_key mesh_vpn
        fi

    fi
}


################################################################################
# Get/Set radio0, radio1 _mesh_ enable state
# Values: 0 or 1
################################################################################
ff_mesh_radio0_disabled() {
    if [ -z "$1" ]; then

        # No argument - retrieve value
        # If key is not found, return empty string.
        # radio0 may as well be undefined.
        ff_sshcmd uci get wireless.mesh_radio0.disabled

    else

        # Set new value.
        ff_sshcmde uci set wireless.mesh_radio0.disabled=$1
        ff_sshcmde uci commit wireless
        ff_sshcmde wifi

    fi
    
}


ff_mesh_radio1_disabled() {
    if [ -z "$1" ]; then

        # No argument - retrieve value
        # If key is not found, return empty string.
        # radio1 may as well be undefined.
        ff_sshcmd uci get wireless.mesh_radio1.disabled

    else

        # Set new value.
        ff_sshcmde uci set wireless.mesh_radio1.disabled=$1
        ff_sshcmde uci commit wireless
        ff_sshcmde wifi

    fi
    
}


################################################################################
# Get/Set radio0, radio1 _client_ enable state (PC WLAN clients)
# Values: 0 or 1
################################################################################
ff_client_radio0_disabled() {
    if [ -z "$1" ]; then

        # No argument - retrieve value
        # If key is not found, return empty string.
        # radio0 may as well be undefined.
        ff_sshcmd uci get wireless.client_radio0.disabled

    else

        # Set new value.
        ff_sshcmde uci set wireless.client_radio0.disabled=$1
        ff_sshcmde uci commit wireless
        ff_sshcmde wifi

    fi
    
}


ff_client_radio1_disabled() {
    if [ -z "$1" ]; then

        # No argument - retrieve value
        # If key is not found, return empty string.
        # radio1 may as well be undefined.
        ff_sshcmd uci get wireless.client_radio1.disabled

    else

        # Set new value.
        ff_sshcmde uci set wireless.client_radio1.disabled=$1
        ff_sshcmde uci commit wireless
        ff_sshcmde wifi

    fi
    
}


################################################################################
# Get/Set radio0/1 frequency.
# Values: 1..?
################################################################################
ff_radio0_channel() {
    if [ -z "$1" ]; then

        # No argument - retrieve value
        ff_sshcmd uci get wireless.radio0.channel

    else

        # Set new value.
        ff_sshcmde uci set wireless.radio0.channel=$1
        ff_sshcmde uci commit wireless
        ff_sshcmde uci set gluon-core.@wireless[0].preserve_channels='1'
        ff_sshcmde uci commit gluon-core
        # Restart WiFi network
        # Use 'iwinfo' to check whether settings from gluon were
        # really accepted by the network stack of linux.
        ff_sshcmde wifi

    fi
    
}

ff_radio1_channel() {
    if [ -z "$1" ]; then

        # No argument - retrieve value
        ff_sshcmd uci get wireless.radio1.channel

    else

        # Set new value.
        ff_sshcmde uci set wireless.radio1.channel=$1
        ff_sshcmde uci commit wireless
        ff_sshcmde uci set gluon-core.@wireless[1].preserve_channels='1'
        ff_sshcmde uci commit gluon-core
        # Restart WiFi network
        ff_sshcmde wifi

    fi
    
}


################################################################################
# Tells whether the channel number should be preserved over a reboot.
# We usually want this and warn, if not set so (ffm_channel_selector)
################################################################################
ff_radio0_preserve_channel() {
    if [ -z "$1" ]; then

        # No argument - retrieve value
        ff_sshcmd uci get gluon-core.@wireless[0].preserve_channels

    else

        # Set new value.
        ff_sshcmde uci set gluon-core.@wireless[0].preserve_channels=$1

    fi
}

ff_radio1_preserve_channel() {
    if [ -z "$1" ]; then

        # No argument - retrieve value
        ff_sshcmd uci get gluon-core.@wireless[1].preserve_channels

    else

        # Set new value.
        ff_sshcmde uci set gluon-core.@wireless[1].preserve_channels=$1

    fi  
}


################################################################################
# Get/Set radio0/1 hwmode
# Values: Each radio should display a value "hwmode".
# 11g or 11ng are 2.4GHz, 11a or 11na are 5GHz.
################################################################################
ff_radio0_hwmode() {
    if [ -z "$1" ]; then

        # No argument - retrieve value
        ff_sshcmd uci get wireless.radio0.hwmode

    else

        # Set new value.
        echo "ff_radio0_hwmode() - ERROR: cannot set this value." 1>&2
        read x
    fi
    
}


ff_radio1_hwmode() {
    if [ -z "$1" ]; then

        # No argument - retrieve value
        ff_sshcmd uci get wireless.radio1.hwmode

    else

        # Set new value.
        echo "ff_radio1_hwmode() - ERROR: cannot set this value." 1>&2
        read x
    fi
    
}


################################################################################
# Read/write the wifi button mode (see ffm_wifi_button_options for list of values)
################################################################################
ff_wifi_btn_mode() {
    if [ -z "$1" ]; then

        # No argument - retrieve value
        ff_sshcmd uci get button-bind.wifi.function

    else

        # Set new value.
        ff_sshcmde uci set button-bind.wifi.function=$1
        ff_sshcmde uci commit button-bind
    fi
}


################################################################################
# Read out several system settings and store them into global variables (g_xxx)
# This function is called in every ffm_main cycle for update reasons.
################################################################################
ff_readsettings() {
    # g_xxx for global variables

    echo "------------------------------------------------------------"
    echo "Reading system configuration."
    echo "Please don't get confused by error messages."
    echo "They happen, when certain features of a router are missing."
    echo "This will take a while."
    echo "------------------------------------------------------------"

    g_hostname=`ff_pretty_hostname`
    g_contact=`ff_contact`
    g_mesh_wan_disabled=`ff_mesh_wan_disabled`
    g_mesh_lan_disabled=`ff_mesh_lan_disabled`
    g_sys_model=`ff_sys_model`
    g_sys_lan_ifnames=`ff_sys_lan_ifnames`
    g_client_interfaces=`ff_client_interfaces`
    g_mesh_vpn_enabled=`ff_mesh_vpn_enabled`
    g_share_location=`ff_share_location`
    g_autoupdate_enabled=`ff_autoupdate_enabled`
    g_autoupdate_branch=`ff_autoupdate_branch`

    g_client_radio0_disabled=`ff_client_radio0_disabled`
    g_mesh_radio0_disabled=`ff_mesh_radio0_disabled`
    g_radio0_channel=`ff_radio0_channel`
    g_radio0_hwmode=`ff_radio0_hwmode`
    g_radio0_freq=""
    if [ "$g_radio0_hwmode" = "11g" -o "$g_radio0_hwmode" = "11ng" ]; then
        g_radio0_freq="2.4GHz"
    elif [ "$g_radio0_hwmode" = "11a" -o "$g_radio0_hwmode" = "11na" ]; then
        g_radio0_freq="5GHz"
    fi
    g_radio0_preserve_channel=`ff_radio0_preserve_channel`

    g_client_radio1_disabled=`ff_client_radio1_disabled`
    g_mesh_radio1_disabled=`ff_mesh_radio1_disabled`
    g_radio1_channel=`ff_radio1_channel`
    g_radio1_hwmode=`ff_radio1_hwmode`
    g_radio1_freq=""
    if [ "$g_radio1_hwmode" = "11g" -o "$g_radio1_hwmode" = "11ng" ]; then
        g_radio1_freq="2.4GHz"
    elif [ "$g_radio1_hwmode" = "11a" -o "$g_radio1_hwmode" = "11na" ]; then
        g_radio1_freq="5GHz"
    fi
    g_radio1_preserve_channel=`ff_radio1_preserve_channel`

    # Convenience variables to have all the word 'enabled' in it.
    # Otherwise, the g_xxx variables are named the same way as uci uses it.
    # Some use 'disabled', some use 'enabled'...
    if [ "$g_mesh_wan_disabled" = "0" ]; then g_mesh_wan_enabled=1; else g_mesh_wan_enabled=0; fi

    # Mesh on LAN may also be empty, if there is no LAN interface.
    if [ "$g_mesh_lan_disabled" = "0" ]; then 
        g_mesh_lan_enabled=1
    elif [ "$g_mesh_lan_disabled" = "1" ]; then 
        g_mesh_lan_enabled=0
    else 
        g_mesh_lan_enabled=
    fi

    g_wifi_btn_mode=`ff_wifi_btn_mode`

    # Debug facility
    if false; then
        echo "g_hostname=$g_hostname"
        echo "g_mesh_wan_disabled=$g_mesh_wan_disabled"
        echo "g_mesh_lan_disabled=$g_mesh_lan_disabled"
        echo "g_sys_model=$g_sys_model"
        read x
    fi

    # This is the title line (upper left) for all dialogs.
    # Update it regularily as well, since the hostname may change.
    dg_backtitle="Freifunk Knot Warlock - $g_sys_model [$g_hostname]"
}


dialog_dbg() {
    echo $*
    read x
}

################################################################################
# dg_setup_vars
# This was taken from the 'dialog' examples.
################################################################################

# These symbols are defined to use in the sample shell scripts to make them
# more readable.  But they are (intentionally) not exported.  If they were
# exported, they would also be visible in the dialog program (a subprocess).

dg_setup_vars() {
    : ${DIALOG=dialog}
    : ${DIALOG_DBG=dialog_dbg}

    : ${DIALOG_OK=0}
    : ${DIALOG_CANCEL=1}
    : ${DIALOG_HELP=2}
    : ${DIALOG_EXTRA=3}
    : ${DIALOG_ITEM_HELP=4}
    : ${DIALOG_ESC=255}

    : ${SIG_NONE=0}
    : ${SIG_HUP=1}
    : ${SIG_INT=2}
    : ${SIG_QUIT=3}
    : ${SIG_KILL=9}
    : ${SIG_TERM=15}
}


################################################################################
# All functions starting with ffm_ are Freifunk menu pages
################################################################################
ffm_mainmenu() {
    while true; do

        # Read from system into ff_xxx variables.
        # Do this in each while-loop cycle to refresh modified values.
        ff_readsettings


        # share location on/off to show this value in the menue immediately
        local share_location_on=off
        if [ "$g_share_location" = "1" ]; then
            share_location_on=on
        fi

        local update_info=""
        if [ "$g_autoupdate_enabled" = "1" ]; then
            if [ "$g_autoupdate_branch" = "stable" ]; then
                update_info="STA";
            else
                update_info="EXP";
            fi
        else
            if [ "$g_autoupdate_branch" = "stable" ]; then
                update_info="sta";
            else
                update_info="exp";
            fi
        fi

        wifi_btn_mode_txt="unknown"
        case $g_wifi_btn_mode in
            0)
                wifi_btn_mode_txt="wifi on/off"
                ;;
            1)
                wifi_btn_mode_txt="none"
                ;;
            2)
                wifi_btn_mode_txt="reset"
                ;;
            3)
                wifi_btn_mode_txt="night1"
                ;;
            4)
                wifi_btn_mode_txt="night2"
                ;;
            5)
                wifi_btn_mode_txt="client on/off"
                ;;
            6)
                wifi_btn_mode_txt="VPN 5h off"
                ;;
            esac

        # Weird I/O redirections were copied from the 'dialog' examples. 
        # Don't know how, but they work.
        # The exitcode and the stdout of 'dialog' (stored in the variable RESULT)
        # are used this way to evaluate the users choice.
        # NOTE that the variable RESULT must be a local variable, otherwise
        # subsequent calls to dialog (hidden in any ffm_xxx function) will
        # overwrite a previous value.
        # also, the exitcode must be evaluated correctly to catch the exitcode
        # from 'dialog' and not any other command. For example
        # local RESULT=`dialog...` will not work, since the exit code then
        # ist set to the result of 'local'!

        # Width of dialogs is probably best over all dialogs with value 70.
        # Height of dialog (15) should be a bit more than menue entries (6).
        # --colors interprets the \\Z<n> escape sequences as ncurses colors
        # To highlight extracted values in the menu directly.

        exec 3>&1
        local RESULT=0
        RESULT=`$DIALOG --clear --backtitle "$dg_backtitle" \
--colors \
--menu "Main Menu" 16 70 8 \
Infosheet "Info Sheet (printout)" \
Names     "Change Names (hostname, owner)   \\Z5[$g_hostname]\\Z0" \
Misc      "Miscellaneous Settigs            \\Z5[loc:$share_location_on upd:\\Z5$update_info]\\Z0" \
MeshOptions "Mesh Options (Mesh on LAN/WAN/VPN)" \
WiFi      "WiFi Options" \
WifiButton "WiFi button mode                 \\Z5[$wifi_btn_mode_txt]\\Z0" \
Speedtest "100MB Download from belwue.net" \
Exit      "Exit to the shell" \
2>&1 1>&3`
        retval=$?
        exec 3>&-

        clear

        case $retval in
            $DIALOG_OK)
                # RESULT contains the keyword of users choice.
                case "$RESULT" in
                    Infosheet)
                        ffm_infosheet
                        ;;
                    Names)
                        ffm_changenames
                        ;;
                    Misc)
                        ffm_miscsettings
                        ;;
                    MeshOptions)
                        ffm_mesh_options
                        ;;
                    WiFi)
                        ffm_wifi_options
                        ;;
                    WifiButton)
                        ffm_wifi_button_options
                        ;;
                    Speedtest)
                        ffm_speedtest
                        ;;
                    Exit)
                        echo "Exited main menu."
                        # Leave while-true loop.
                        break
                        ;;
                    *)
                        echo "Unknown menu entry: $RESULT"
                        echo "(Press ENTER)"
                        read x
                        ;;
                esac
                ;;
            $DIALOG_CANCEL)
                echo "Canceled main menu."
                # Leave while-true loop.
                break
                ;;
            $DIALOG_ESC)
                if test -n "$RESULT" ; then
                    echo "Unexpected ESC result: $RESULT"
                    echo '(Press ENTER)'
                    read x
                    # Leave while-true loop.
                    break
                else
                    echo "ESC pressed."
                    # Leave while-true loop.
                    break
                fi
                ;;
        esac

    done
    # end while true

    exit 0
}


################################################################################
# Info Sheet
################################################################################
ffm_infosheet() {
    # Fill blanks so that variables always consume equally same space
    # for the layout of the 2 column text
    # 2.4GHz or 5GHZ
    # channel 6 or 11
    # hwmode 11 or 11na

    local radio0_freq="$g_radio0_freq"
    while [ `expr "$radio0_freq" : ".*"` -lt 6 ]; do
            radio0_freq="$radio0_freq "
    done
    
    local radio0_hwmode="$g_radio0_hwmode"
    while [ `expr "$radio0_hwmode" : ".*"` -lt 4 ]; do
            radio0_hwmode="$radio0_hwmode "
    done
    
    local radio0_channel="$g_radio0_channel"
    while [ `expr "$radio0_channel" : ".*"` -lt 2 ]; do
        radio0_channel="$radio0_channel "
    done

    # Highlight in red, if channel is not preserved over update
    local radio0_preserve_channel="$g_radio0_preserve_channel"
    if [ -z "$radio0_preserve_channel" ]; then
        # Entry may not exist at all
        radio0_preserve_channel="_"
    fi
    if [ "$radio0_preserve_channel" != "1" ]; then
        radio0_preserve_channel="\Z1\Zb$radio0_preserve_channel\Z0\ZB"
    fi

    local radio1_preserve_channel="$g_radio1_preserve_channel"
    if [ -z "$radio1_preserve_channel" ]; then
        # Entry may not exist at all
        radio1_preserve_channel="_"
    fi
    if [ "$radio1_preserve_channel" != "1" ]; then
        radio1_preserve_channel="\Z1\Zb$radio1_preserve_channel\Z0\ZB"
    fi

    $DIALOG --backtitle "$dg_backtitle" \
        --title "[ Info Sheet ]" \
        --colors \
        --msgbox "\
Hostname:               $g_hostname\n\
Contact:                $g_contact\n\
Share Location:         $g_share_location\n\
Mesh VPN enabled:       $g_mesh_vpn_enabled\n\
Mesh WAN disabled:      $g_mesh_wan_disabled\n\
Mesh LAN disabled:      $g_mesh_lan_disabled\n\
Ch Update preserve:     $radio0_preserve_channel\n\
--radio0--                        --radio1--\n\
hwmode:              $radio0_hwmode $radio0_freq  hwmode:              $g_radio1_hwmode $g_radio1_freq\n\
channel:             $radio0_channel           channel:             $g_radio1_channel\n\
Mesh disabled:       $g_mesh_radio0_disabled            Mesh disabled:       $g_mesh_radio1_disabled\n\
Client disabled:     $g_client_radio0_disabled            Client disabled:     $g_client_radio1_disabled\n\
" 17 80
}


################################################################################
# Menu Host Name
################################################################################
ffm_changenames() {
    exec 3>&1
    local RESULT=0

    # The 'Rename' (extra) button is the default and there is no OK button.
    # Otherwise pressing ENTER will always assume 'OK' 
    # and that seems not very convenient.

    RESULT=`$DIALOG --clear --backtitle "$dg_backtitle"  \
--title "[ Change Names ]" \
--default-button extra \
--no-ok \
--inputmenu "Select entry to modify" 15 70 9 \
Hostname "$g_hostname" \
Contact "$g_contact" \
2>&1 1>&3`
    retval=$?
    exec 3>&-

    case $retval in
        $DIALOG_OK)
            # Edit field did not changed but was only acknowledged.
            ;;
        $DIALOG_EXTRA)
            # Edit field was changed. Content of RESULT is like
            # "RENAMED Hostname test.foo.bar"
            # 'dialog' only returns with this exit code, if the 
            # 'Rename' button was triggered.
            # Only one single textfield may be changed this way.

            # Did the user change the Hostname field? It may not be empty.
            new_hostname=`echo $RESULT | sed 's/RENAMED Hostname //g'`
            if expr "$RESULT" : ".*Hostname" && [ ! -z "$new_hostname" ]; then
                ffm_confirm_cmd ff_pretty_hostname "$new_hostname"
            fi
            
            # Did the user change the contact field? It MAY be empty.
            new_contact=`echo $RESULT | sed 's/RENAMED Contact //g'`
            if expr "$RESULT" : ".*Contact"; then
                ffm_confirm_cmd ff_contact "$new_contact"
            fi
            ;;
        $DIALOG_CANCEL)
            ;;
        $DIALOG_ESC)
            if test -n "$RESULT" ; then
                echo "ESC Result: $RESULT"
            else
                echo "ESC pressed."
            fi
            ;;
        *)
            echo "Unknown exit code $retval, RESULT=$RESULT"
            read x
            ;;
    esac
}


################################################################################
# Menu Miscellaneous Properties
################################################################################
ffm_miscsettings() {
    local share_location_on=on
    if [ "$g_share_location" = "0" ]; then
        share_location_on=off
    elif [ "$g_share_location" != "1" ]; then
        echo "ffm_miscsettings() - invalid value g_share_location=$g_share_location"
        read x
        return
    fi

    update_enabled_on=on
    if [ "$g_autoupdate_enabled" = "0" ]; then
        update_enabled_on=off
    elif [ "$g_autoupdate_enabled" != "1" ]; then
        echo "ffm_miscsettings() - invalid value g_autoupdate_enabled=$g_autoupdate_enabled"
        read x
        return
    fi

    update_stable_on=on
    if [ "$g_autoupdate_branch" = "experimental" ]; then
        update_stable_on=off
    elif [ "$g_autoupdate_branch" != "stable" ]; then
        echo "ffm_miscsettings() - invalid value g_autoupdate_branch=$g_autoupdate_branch"
        read x
        return
    fi

    exec 3>&1
    local RESULT=0
    RESULT=`$DIALOG --clear --backtitle "$dg_backtitle"  \
--title "[ Miscellaneous Options ]" \
--checklist "Miscellaneous Options" 12 70 5 \
share_location "Share location on map" $share_location_on \
upd_enabled "Autoupdater enabled" $update_enabled_on \
upd_stable "Use stable branch" $update_stable_on \
2>&1 1>&3`
    retval=$?
    exec 3>&-

    case $retval in
        $DIALOG_OK)
            # Update WAN setting
            echo "g_share_location=$g_share_location"
            echo "$RESULT"
            if expr "$RESULT" : ".*share_location" >/dev/null; then
                # share_location is 'checked'.
                # If it was inactive before, activate it now.
                if [ "$g_share_location" != "1" ]; then
                    ffm_confirm_cmd ff_share_location 1
                fi
            else
                # share_location is 'unchecked'.
                # If it was active before, de-activate it now.
                if [ "$g_share_location" = "1" ]; then
                    ffm_confirm_cmd ff_share_location 0
                fi
            fi

            # Autoupdate Enabled?
            if expr "$RESULT" : ".*upd_enabled" >/dev/null; then
                # update_enabled was 'checked'.
                # If it was de-activated before, activate it now.
                if [ "$g_autoupdate_enabled" != "1" ]; then
                    ffm_confirm_cmd ff_autoupdate_enabled 1
                fi
            else
                # update_enabled was 'un-checked'.
                # If it was activated before, de-activate it now.
                if [ "$g_autoupdate_enabled" != "0" ]; then
                    ffm_confirm_cmd ff_autoupdate_enabled 0
                fi
            fi

            # Autoupdate branch name
            if expr "$RESULT" : ".*upd_stable" >/dev/null; then
                # Only change this value in UCI, if the user has
                # really changed it. Otherwise we can easily force to
                # download a new firmware and reboot with no reason.
                # And this makes the host go offline for sure.
                if [ "$g_autoupdate_branch" != "stable" ]; then
                    ffm_confirm_cmd ff_autoupdate_branch stable
                fi
            else
                if [ "$g_autoupdate_branch" != "experimental" ]; then
                    ffm_confirm_cmd ff_autoupdate_branch experimental
                fi
            fi

            ;;

        $DIALOG_CANCEL)
            ;;
        $DIALOG_ESC)
            ;;
        *)
            echo "ffm_miscsettings() - Unknown exit code $retval, RESULT=$RESULT"
            read x
            ;;
    esac

}


################################################################################
# Menu Mesh Options
################################################################################
ffm_mesh_options() {
    # Generate the words "on" and "off" for 'dialog'.
    # Query global cache variables, they will be refreshed in the main menu loop.

    local mesh_wan_on=off
    if [ "$g_mesh_wan_disabled" = '0' ]; then
        mesh_wan_on=on
    elif [ "$g_mesh_wan_disabled" != '1' ]; then
        echo "ffm_mesh_options() - invalid value g_mesh_wan_disabled=$g_mesh_wan_disabled"
        read x
        return
    fi

    # Mesh on LAN may be empty if there is no local LAN port available.
    local mesh_lan_on
    if [ "$g_mesh_lan_disabled" = '0' ]; then
        mesh_lan_on=on
    elif [ "$g_mesh_lan_disabled" = '1' ]; then
        mesh_lan_on=off
    fi

    local mesh_vpn_on=on
    if [ "$g_mesh_vpn_enabled" = "0" ]; then
        mesh_vpn_on=off
    elif [ "$g_mesh_vpn_enabled" != "1" ]; then
        echo "ffm_mesh_options() - invalid value g_mesh_vpn_enabled=$g_mesh_vpn_enabled"
        read x
        return
    fi


    # Loop so that the help option can restart this dialog.
    # all other dialog actions break out.
    while true; do

        exec 3>&1
        local RESULT=0
        if [ ! -z "$mesh_lan_on" ]; then
            RESULT=`$DIALOG --clear --backtitle "$dg_backtitle"  \
--title "[ Mesh Options ]" \
--help-button \
--checklist "available LAN ifaces: [$g_sys_lan_ifnames]\n\
PC-client network on: [$g_client_interfaces]" 12 70 5 \
mesh_wan "Mesh on WAN (blue uplink port)" $mesh_wan_on \
mesh_lan "Mesh on LAN (yellow switch ports)" $mesh_lan_on \
mesh_vpn "Mesh VPN" $mesh_vpn_on \
2>&1 1>&3`
            retval=$?
        else
            RESULT=`$DIALOG --clear --backtitle "$dg_backtitle"  \
--title "[ Mesh Options ]" \
--help-button \
--checklist "available LAN ifaces: [$g_sys_lan_ifnames]\n\
PC-client network on: [$g_client_interfaces]" 12 70 5 \
mesh_wan "Mesh on WAN (blue uplink port)" $mesh_wan_on \
mesh_vpn "Mesh VPN" $mesh_vpn_on \
2>&1 1>&3`
            retval=$?
        fi
        exec 3>&-

        # RESULT contains the checkbox option name(s), if option is checked:
        # "mesh_wan mesh_lan" or "mesh_lan"

        case $retval in
            $DIALOG_OK)
                local need_restart=0

                # Update WAN setting
                if expr "$RESULT" : ".*mesh_wan" >/dev/null; then
                    if [ "$g_mesh_wan_disabled" != "0" ]; then
                        ffm_confirm_cmd ff_mesh_wan_disabled 0
                        need_restart=1
                    fi
                else
                    if [ "$g_mesh_wan_disabled" != "1" ]; then
                        ffm_confirm_cmd ff_mesh_wan_disabled 1
                        need_restart=1
                    fi
                fi

                # Update LAN setting, if there is a LAN interface
                if [ ! -z "$mesh_lan_on" ]; then
                    if expr "$RESULT" : ".*mesh_lan" >/dev/null; then
                        if [ "$g_mesh_lan_disabled" != "0" ]; then
                            ffm_confirm_cmd ff_mesh_lan_disabled 0
                            need_restart=1
                        fi
                    else
                        if [ "$g_mesh_lan_disabled" != "1" ]; then
                            ffm_confirm_cmd ff_mesh_lan_disabled 1
                            need_restart=1
                        fi
                    fi
                fi

                # Update MeshVPN setting
                if expr "$RESULT" : ".*mesh_vpn" >/dev/null; then
                    if [ "$g_mesh_vpn_enabled" != "1" ]; then
                        ffm_confirm_cmd ff_mesh_vpn_enabled 1
                        need_restart=1
                    fi
                else
                    if [ "$g_mesh_vpn_enabled" != "0" ]; then
                        ffm_confirm_cmd ff_mesh_vpn_enabled 0
                        need_restart=1
                    fi
                fi

                # Show wait dialog for '/etc/init.d/network restart'
                if [ "$need_restart" = "1" ]; then
                    ffm_network_restart
                fi

                # break while true loop
                break;
                ;;

            $DIALOG_HELP)
                # RESULT="HELP mesh_lan"
                $DIALOG  --clear --backtitle "$dg_backtitle"  \
                    --title "[ Help - Mesh Options ]" \
                    --msgbox "Mesh on WAN (blue)/LAN (yellow):\n\n\
If turned ON:\n\
Do NOT connect an internet connection on that port. \n\
Do NOT connect a client PC on that port.\n\
Instead, connect another FF router with mesh enabled on that port.\n\n\
This connection is faster, since only one router has to do VPN \
encryption. Or use an Offloader.\n\n\
Default is OFF, and meshing only happens over WLAN.\n\n\
Routers with only one single port: probably one must try\n\
LAN or WAN to find the right interface.\n\n\
Mesh VPN: allow the router to share its own internet connection\n\
with other routers via WiFi. Usually you want this enabled." 20 70
                # No break here, go back to start of while loop
                ;;
            $DIALOG_CANCEL)
                # break while true loop
                break;
                ;;
            $DIALOG_ESC)
                # break while true loop
                break;
                ;;
            *)
                echo "ffm_mesh_options() - Unknown exit code $retval, RESULT=$RESULT"
                read x
                # break while true loop
                break;
                ;;
        esac

    done
    # while true loop for help functionality
}


################################################################################
# Menu WiFi
################################################################################
ffm_wifi_options() {
    # radio0 ------------------
    local mesh_radio0_on=ff
    if [ "$g_mesh_radio0_disabled" = "0" ]; then
        mesh_radio0_on=on
    elif [ "$g_mesh_radio0_disabled" != "1" ]; then
        echo "ffm_wifi_options() - invalid value g_mesh_radio0_disabled=$g_mesh_radio0_disabled"
        echo "Should be '0' or '1'".
        echo "There must be at least one WiFi interface available."
        echo -n "Press ENTER..."
        read x
        return
    fi

    local client_radio0_on=ff
    if [ "$g_client_radio0_disabled" = "0" ]; then
        client_radio0_on=on
    elif [ "$g_client_radio0_disabled" != "1" ]; then
        echo "ffm_wifi_options() - invalid value g_client_radio0_disabled=$g_client_radio0_disabled"
        echo "Should be '0' or '1'".
        echo "There must be at least one WiFi interface available."
        echo -n "Press ENTER..."
        read x
        return
    fi

    # radio1 ------------------
    local has_radio1=0
    local mesh_radio1_on=off
    local client_radio1_on=ff

    # Check whether radio1 exists at all
    if [ ! -z "$g_mesh_radio1_disabled" ]; then
        has_radio1=1
        if [ "$g_mesh_radio1_disabled" != "1" ]; then
            mesh_radio1_on=on
        fi

        if [ "$g_client_radio1_disabled" != "1" ]; then
            client_radio1_on=on
        fi
    fi

    # Check whether channels are preserved during update
    local radio0_preserve_message=""
    local radio1_preserve_message=""

    if [ "$g_radio0_preserve_channel" != "1" ]; then
        radio0_preserve_message="\Z1(!)\Z0"
    fi
    if [ "$g_radio1_preserve_channel" != "1" ]; then
        radio1_preserve_message="\Z1(!)\Z0"
    fi

    local RESULT=""
    local retval=0

    exec 3>&1

    if [ "$has_radio1" = "1" ]; then
        # One menu with radio0 and radio1
        RESULT=`$DIALOG --clear --backtitle "$dg_backtitle"  \
--title "[ WiFi Options ]" \
--colors \
--help-button --help-label "Change Channel" \
--checklist "WiFi Options" 12 70 4 \
mesh_radio0 "radio0 Mesh enabled [$g_radio0_freq Ch-$g_radio0_channel $radio0_preserve_message]" $mesh_radio0_on \
client_radio0 "radio0 Client enabled" $client_radio0_on \
mesh_radio1 "radio1 Mesh enabled [$g_radio1_freq Ch-$g_radio1_channel $radio1_preserve_message]" $mesh_radio1_on \
client_radio1 "radio1 Client enabled" $client_radio1_on \
2>&1 1>&3`
        retval=$?
    else
        # And another menu for only radio0
        # Highlight default channel 6 if chosen.
        if [ "$g_radio0_channel" == "6" ]; then
            default="(dflt)"
        else
            default=""
        fi
        RESULT=`$DIALOG --clear --backtitle "$dg_backtitle"  \
--title "[ WiFi Options ]" \
--colors \
--help-button --help-label "Change Channel" \
--checklist "WiFi Options" 12 70 4 \
mesh_radio0 "radio0 Mesh enabled [$g_radio0_freq Ch-$g_radio0_channel $default $radio0_preserve_message]" $mesh_radio0_on \
client_radio0 "radio0 Client enabled" $client_radio0_on \
2>&1 1>&3`
        retval=$?
    fi

    exec 3>&-

    # RESULT contains the checkbox option name(s), if option is checked, e.g.:
    # "mesh_radio0 mesh_radio1" or "mesh_client_radio1"

    case $retval in
        $DIALOG_OK)

            # radio0
            # ----------
            # Update Mesh 
            if expr "$RESULT" : ".*mesh_radio0" >/dev/null; then
                if [ "$g_mesh_radio0_disabled" = "1" ]; then
                    # Change state disabled->enabled
                    ffm_confirm_cmd ff_mesh_radio0_disabled 0
                fi
            else
                if [ "$g_mesh_radio0_disabled" = "0" ]; then
                    # Change state enabled->disabled
                    ffm_confirm_cmd ff_mesh_radio0_disabled 1
                fi
            fi

            # Update Client radio0
            if expr "$RESULT" : ".*client_radio0" >/dev/null; then
                if [ "$g_client_radio0_disabled" = "1" ]; then
                    # Change state disabled->enabled
                    ffm_confirm_cmd ff_client_radio0_disabled 0
                fi
            else
                if [ "$g_client_radio0_disabled" = "0" ]; then
                    # Change state enabled->disabled
                    ffm_confirm_cmd ff_client_radio0_disabled 1
                fi
            fi

            # radio1
            # ----------
            # Update Mesh
            if expr "$RESULT" : ".*mesh_radio1" >/dev/null; then
                if [ "$g_mesh_radio1_disabled" = "1" ]; then
                    # Change state disabled->enabled
                    ffm_confirm_cmd ff_mesh_radio1_disabled 0
                fi
            else
                if [ "$g_mesh_radio1_disabled" = "0" ]; then
                    # Change state enabled->disabled
                    ffm_confirm_cmd ff_mesh_radio1_disabled 1
                fi
            fi

            # Update Client radio1
            if expr "$RESULT" : ".*client_radio1" >/dev/null; then
                if [ "$g_client_radio1_disabled" = "1" ]; then
                    # Change state disabled->enabled
                    ffm_confirm_cmd ff_client_radio1_disabled 0
                fi
            else
                if [ "$g_client_radio1_disabled" = "0" ]; then
                    # Change state enabled->disabled
                    ffm_confirm_cmd ff_client_radio1_disabled 1
                fi
            fi
            ;;

        $DIALOG_HELP)
            # Abuse the Help button to get the currently highlighted field name.
            # We derive from that, which radio (0/1) we want to modify. Example:
            # echo RESULT=$RESULT
            # RESULT=HELP mesh_radio0

            # Extract 'radio0' or 'radio1':
            radio_name=`echo $RESULT | sed 's/.*\(radio.\)/\1/g'`

            ffm_channel_selector $radio_name
            ;;

        $DIALOG_CANCEL)
            ;;
        $DIALOG_ESC)
            ;;
        *)
            echo "ffm_wifi_options() - Unknown exit code $retval, RESULT=$RESULT"
            read x
            ;;
    esac

}


################################################################################
# Menu to select channel for given radio0/1
# Argument: 'radio0' or 'radio1'.
################################################################################
ffm_channel_selector() {
    # radio0 or radio1:
    device=$1

    # Construct the variable name e.g. g_radio0_freq and evaluate the content
    # of this variable, i.e. $g_radio0_freq -> "5GHz'
    device_freq_name=g_${device}_freq
    device_freq=`eval echo \\$"$device_freq_name"`

    device_channel_name=g_${device}_channel
    device_channel=`eval echo \\$"$device_channel_name"`

    local radio0_preserve_message=""
    local radio1_preserve_message=""

    if [ "$device" = "radio0" -a "$g_radio0_preserve_channel" != "1" ]; then
        radio0_preserve_message="\n\Z1\ZbWarning: radio0 does not preserve channel over fw update!\Z0\ZB"
    fi
    if [ "$device" = "radio1" -a "$g_radio1_preserve_channel" != "1" ]; then
        radio1_preserve_message="\n\Z1\ZbWarning: radio1 does not preserve channel over fw update!\Z0\ZB"
    fi

    local RESULT=""
    local retval=0

    # For a complete channel list see
    # https://wiki.freifunk-franken.de/w/WLAN_Frequenzen

    # -------------------- 5GHz

    if [ "$device_freq" = "5GHz" ]; then

        ch34_on=`test $device_channel = 34 && echo on || echo off`
        ch36_on=`test $device_channel = 36 && echo on || echo off`
        ch38_on=`test $device_channel = 38 && echo on || echo off`
        ch40_on=`test $device_channel = 40 && echo on || echo off`
        ch42_on=`test $device_channel = 42 && echo on || echo off`
        ch44_on=`test $device_channel = 44 && echo on || echo off`
        ch46_on=`test $device_channel = 46 && echo on || echo off`
        ch48_on=`test $device_channel = 48 && echo on || echo off`

        ch52_on=`test $device_channel = 52 && echo on || echo off`
        ch56_on=`test $device_channel = 56 && echo on || echo off`
        ch60_on=`test $device_channel = 60 && echo on || echo off`
        ch64_on=`test $device_channel = 64 && echo on || echo off`

        ch100_on=`test $device_channel = 100 && echo on || echo off`
        ch104_on=`test $device_channel = 104 && echo on || echo off`
        ch108_on=`test $device_channel = 108 && echo on || echo off`
        ch112_on=`test $device_channel = 112 && echo on || echo off`
        ch116_on=`test $device_channel = 116 && echo on || echo off`
        ch120_on=`test $device_channel = 120 && echo on || echo off`
        ch124_on=`test $device_channel = 124 && echo on || echo off`
        ch128_on=`test $device_channel = 128 && echo on || echo off`
        ch132_on=`test $device_channel = 132 && echo on || echo off`
        ch136_on=`test $device_channel = 136 && echo on || echo off`
        ch140_on=`test $device_channel = 140 && echo on || echo off`

        # --no-tags eliminates the tag names (34, 36 etc) since they 
        # are the same as the textual description.

        exec 3>&1
        RESULT=`$DIALOG --clear --backtitle "$dg_backtitle"  \
--title "[ WiFi Channel $device $device_freq Ch-$device_channel ]" \
--no-tags \
--colors \
--radiolist "Select WiFi Channel $radio0_preserve_message $radio1_preserve_message" 20 70 20 \
34 34 $ch34_on \
36 36 $ch36_on \
38 38 $ch38_on \
40 40 $ch40_on \
42 42 $ch42_on \
44 "44 (default)" $ch44_on \
46 46 $ch46_on \
48 48 $ch48_on \
52 52 $ch52_on \
56 56 $ch48_on \
60 60 $ch60_on \
64 64 $ch64_on \
100 100 $ch100_on \
104 104 $ch104_on \
108 108 $ch108_on \
112 112 $ch112_on \
116 "116 Radar start" $ch116_on \
120 "120 Radar" $ch120_on  \
124 "124 Radar" $ch124_on \
128 "128 Radar" $ch128_on \
132 "132 Radar end" $ch132_on \
136 136 $ch136_on \
140 140 $ch140_on \
2>&1 1>&3`
        retval=$?
        exec 3>&-

    # -------------------- 2.4GHz

    elif [ "$device_freq" = "2.4GHz" ]; then

        ch1_on=`test $device_channel = 1 && echo on || echo off`
        ch2_on=`test $device_channel = 2 && echo on || echo off`
        ch3_on=`test $device_channel = 3 && echo on || echo off`
        ch4_on=`test $device_channel = 4 && echo on || echo off`
        ch5_on=`test $device_channel = 5 && echo on || echo off`
        ch6_on=`test $device_channel = 6 && echo on || echo off`
        ch7_on=`test $device_channel = 7 && echo on || echo off`
        ch8_on=`test $device_channel = 8 && echo on || echo off`
        ch9_on=`test $device_channel = 9 && echo on || echo off`
        ch10_on=`test $device_channel = 10 && echo on || echo off`
        ch11_on=`test $device_channel1 = 11 && echo on || echo off`
        ch12_on=`test $device_channel = 12 && echo on || echo off`
        ch13_on=`test $device_channel = 13 && echo on || echo off`

        exec 3>&1
        RESULT=`$DIALOG --clear --backtitle "$dg_backtitle"  \
--title "[ WiFi Channel $device $device_freq Ch-$device_channel ]" \
--default-item 38 \
--no-tags \
--colors \
--radiolist "Select WiFi Channel $radio0_preserve_message $radio1_preserve_message" 20 70 20 \
1 1 $ch1_on \
2 2 $ch2_on \
3 3 $ch3_on \
4 4 $ch4_on \
5 5 $ch5_on \
6 "6 (default)" $ch6_on \
7 7 $ch7_on \
8 8 $ch8_on \
9 9 $ch9_on \
10 10 $ch10_on \
11 11 $ch11_on \
12 12 $ch12_on \
13 13 $ch13_on \
2>&1 1>&3`

        retval=$?
        exec 3>&-

    else
        echo "ffm_channel_selector() - Error: Unknown frequency: $device_freq"
        read x
        return
    fi

    case $retval in
        $DIALOG_OK)
            # RESULT contains the keyword of users choice.
            case "$RESULT" in
                [0-9]*)
                    channel_nr=$RESULT
                    if [ "$device" = "radio0" ]; then
                        ffm_confirm_cmd ff_radio0_channel $channel_nr
                    elif [ "$device" = "radio1" ]; then
                        ffm_confirm_cmd ff_radio1_channel $channel_nr
                    else
                        echo "ffm_channel_selector() - Error: unknown device: $device"
                        read x
                        return
                    fi
                    ;;
                
                *)
                    echo "ffm_channel_selector() - Error: unknown menu option: $RESULT"
                    read x
                    return
                    ;;
            esac
            ;;

        $DIALOG_CANCEL)
            ;;
        $DIALOG_ESC)
            ;;

    esac
    
}


################################################################################
# Change the WiFi button mode:
# https://github.com/tecff/gluon-packages/tree/master/tecff-button-bind
#    0 - WLAN an/aus
#    1 - Keine Funktion (default)
#    2 - WLAN-Reset
#    3 - Nachtmodus 1, alle Status-LEDs an/aus
#    4 - Nachtmodus 2, aber während Taster-Betätigung an
#    5 - Client-Netz an/aus
#    6 - Mesh-VPN aus für 5 Stunden
################################################################################
ffm_wifi_button_options() {

   btn0_on=`test $g_wifi_btn_mode = 0 && echo on || echo ff`
   btn1_on=`test $g_wifi_btn_mode = 1 && echo on || echo ff`
   btn2_on=`test $g_wifi_btn_mode = 2 && echo on || echo ff`
   btn3_on=`test $g_wifi_btn_mode = 3 && echo on || echo ff`
   btn4_on=`test $g_wifi_btn_mode = 4 && echo on || echo ff`
   btn5_on=`test $g_wifi_btn_mode = 5 && echo on || echo ff`
   btn6_on=`test $g_wifi_btn_mode = 6 && echo on || echo ff`

    exec 3>&1
    RESULT=`$DIALOG --clear --backtitle "$dg_backtitle"  \
--title "[ WiFi Button Mode ]" \
--no-tags \
--colors \
--radiolist "Select WiFi button mode" 15 70 7 \
0 "0 - WiFi on/off" $btn0_on \
1 "1 - No function (default)" $btn1_on \
2 "2 - WiFi Reset" $btn2_on \
3 "3 - night mode 1, all LEDs off" $btn3_on \
4 "4 - night mode 2, LEDs off, on when pressing button" $btn4_on \
5 "5 - Toggle client network on/off" $btn5_on \
6 "6 - Mesh-VPN off for 5 hours" $btn6_on \
2>&1 1>&3`
    retval=$?
    exec 3>&-

    case $retval in
        $DIALOG_OK)
            # RESULT contains the keyword of users choice.
            case "$RESULT" in
                [0-9]*)
                    wifi_btn_mode=$RESULT
                    ffm_confirm_cmd ff_wifi_btn_mode $wifi_btn_mode
                    ;;
                
                *)
                    echo "ffm_wifi_button_options() - Error: unknown menu option: $RESULT"
                    read x
                    return
                    ;;
            esac
            ;;

        $DIALOG_CANCEL)
            ;;
        $DIALOG_ESC)
            ;;

    esac

}


################################################################################
# Perform a 100MB download on the console, dump data to /dev/null
################################################################################

ffm_speedtest() {
    # This gives us also the CPU load before wget starts to torture the system.
    start_uptime=`uptime`

    # seconds since 1970
    start_seconds=`date +%s`
    ff_sshcmde wget -O/dev/null http://speedtest.belwue.net/100M

    # Calculate kBits/sec
    end_seconds=`date +%s`
    seconds_delta=`expr $end_seconds - $start_seconds`
    kbits_per_second=`expr 1000000 / $seconds_delta`
    end_uptime=`uptime`

    # Show result in a nice confirm box.
    # No need to evaluate the return code here.
    $DIALOG --clear --backtitle "$dg_backtitle" --title "[ Speedtest Result ]" --msgbox \
"Transfer rate: ===> $kbits_per_second kBit/sec, 100MB in $seconds_delta seconds.\n\
Compare sysload before and after wget:\n\
Before: $start_uptime\n\
After:  $end_uptime" \
10 85

    echo 'For comparison here is the localhosts wget speed:'
    wget -O/dev/null http://speedtest.belwue.net/100M
    # Usually a full blown wget prints out the MBits/sec already,
    # so there is no need to calculate it via 'expr'.

    echo "Press ENTER..."
    read x
}


################################################################################
# Confirm Dialog "Execute command...?"
#
# Take all the args, show it to user and ask to confirm.
# If 'Yes', then execute the args as command.
################################################################################

ffm_confirm_cmd() {
    # Use "$@" to transfer the given args as-is to the sub-command.
    # E.g. 
    # ffm_confirm_cmd testscript "multi word argument" second third
    # 
    # will call 'testscript' with 3 parameters: 
    # 1 - multi word argument
    # 2 - second
    # 3 - third
    
    # Use "$*" to create one single word:
    # 1 - multi word argument second third

    exec 3>&1
    local RESULT=0
    RESULT=`$DIALOG --clear --backtitle "$dg_backtitle" \
--title "[ Confirm Command ]" \
--yesno "$*" 10 70 \
2>&1 1>&3`
    retval=$?
    exec 3>&-
 
    case $retval in
    $DIALOG_OK)
        echo "Executing: $*"
        # Enable the following line to actually execute command:
        "$@"
        echo "Press ENTER"
        read x
        ;;
    $DIALOG_CANCEL)
        ;;
    $DIALOG_ESC)
        ;;
    *)
        echo "Unknown exit code $retval, RESULT=$RESULT"
        read x
        ;;
    esac

}


################################################################################
# Info Dialog (without confirm button) "Restarting network... please wait."
################################################################################

ffm_network_restart() {
    $DIALOG --backtitle "$dg_backtitle" \
    --title "[ Restart Network ]" \
    --infobox "Restaring network...\n\
Please wait up to 2min." 10 70
 
    ff_sshcmd /etc/init.d/network restart
    echo "Restart Done."
}



################################################################################
# Test function which can be called before the ffm_main() in order
# to try out various 'dialog' parameters.
# Usually, the g_xxx variables ar not initialized yet, since that takes
# a reasonable amount of time.
################################################################################
ffm_test() {
    dialog --backtitle "Backtitle"  \
--title "[ WiFi Options ]" \
--checklist "WiFi Options" 12 70 5 \
radio0_on "radio0 Enabled" on \
radio1_on "radio1 Enabled" off \
--inputmenu "Change Pretty Hostname" 12 70 3 hostname "My Hostname"

    read x
    exit

}

################################################################################
# main - starts here
################################################################################

# All sshcmd calls need g_node and sshcmd to be set properly.
# Initialize them once here, they will never change.

# ffm_test

g_node_ip=$1
if [ -z "$g_node_ip" ]; then
    echo "Error: Please support a valid IPV6t address as argument." 1>&2
    echo "Exiting." 2>&1
    exit 1
fi

# Set some variables for the 'dialog' program like DIALOG_OK, DIALOG_CANCEL etc.
# (The FF specific global cache variables are re-read in each main menu cycle).
dg_setup_vars



if [ -z `ff_pretty_hostname` ]; then
    echo "Unable to connect to router (cannot read hostname)." 1>&2
    exit 1
fi

# Launch main menu
ffm_mainmenu

exit 0

blutsauger 2020/05/06 06:59

bastelprojekte/menuconfig.txt · Zuletzt geändert: 2020/06/17 02:02 von blutsauger