Benutzer-Werkzeuge

Webseiten-Werkzeuge


bastelprojekte:menuconfig

Dies ist eine alte Version des Dokuments!


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.

#!/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 ass 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 "$@"
    if [ $? != 0 ]; then
        echo "Error in: $@" 1>&2
    fi
}

################################################################################
# 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_sshcmd uci set button-bind.wifi.function=$1
    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 "Reading system configuration..."

    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\
--radio0--                        --radio1--\n\
hwmode:              $radio0_hwmode $radio0_freq  hwmode:              $g_radio1_hwmode $g_radio1_freq\n\
channel:             $radio0_channel           channel:             $g_radio1_channel\n\
Ch Update preserve:  $radio0_preserve_channel            Ch Update preserve:  $radio1_preserve_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 than to daisy-chain a second routers uplink (blue) \
into the regular PC port (LAN, yellow).\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\
Mesh VPN: enable this, to allow user clients to connect to the internet.\n\
Usually you want this enabled. Except the router is only used to\n\
forward packets without allowing user client connections." 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"
        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"
        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.1588742184.txt.gz · Zuletzt geändert: 2020/05/06 05:16 von blutsauger

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki