diff --git a/bin/txt_compile_exec b/bin/txt_compile_exec
new file mode 100644
index 0000000000000000000000000000000000000000..86f5bd3f08eb059952cf9b2c1be2d0960ea26ffa
--- /dev/null
+++ b/bin/txt_compile_exec
@@ -0,0 +1,20 @@
+#!/bin/bash
+src_file=$(realpath "$1")
+src_folder=$(dirname "$src_file")
+src_filename=$(basename -- "$src_file")
+extension="${src_filename##*.}"
+if [ "$extension" == "cpp" ]
+then
+  COMPILER="/usr/bin/g++"
+else
+
+  COMPILER="/usr/bin/gcc"
+fi
+
+binfile=$src_folder/"${src_filename%.*}"
+FLAGS="-Wall -Wpedantic -Wextra -Wfatal-errors -I/usr/include/ft/ -lm -lcftlock -lTxtControlLib -L/usr/lib -o $binfile"
+
+$COMPILER $FLAGS $1
+chmod +x $binfile
+
+sudo -u ftgui $binfile
\ No newline at end of file
diff --git a/bin/txt_nodered b/bin/txt_nodered
new file mode 100755
index 0000000000000000000000000000000000000000..b311f6cd9fc822d1477f36f508e5983de8809c7f
--- /dev/null
+++ b/bin/txt_nodered
@@ -0,0 +1,73 @@
+#!/bin/sh
+# Script-helper to control node-red server service
+#
+#  Copyright (c) 2023 Manuel Schreiner, Accso. All rights reserved.
+#
+#  SPDX-License-Identifier: Apache-2.0
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+# Usage
+
+usage()
+{
+  echo "Usage: sudo txt_nodered <on|off|status>"
+}
+
+# Assigning arguments
+
+action="${1}"
+
+# Setttings
+
+nodered_service='node-red'
+
+# Arguments verification
+
+. /usr/share/txt2-utils/txt_aux_functions
+
+# Main
+
+check_nargs "$#" 1
+case "${action}" in
+  'on')
+    err=0
+    /bin/systemctl start "${nodered_service}" || err=$?
+    ;;
+  'off')
+    err=0
+    /bin/systemctl stop "${nodered_service}" || err=$?
+    ;;
+  'status')
+    state1="$(/bin/systemctl is-active "${nodered_service}")"
+    err=0
+    if [ "${state1}" = 'active' ]; then
+      echo "NODERED:ON"
+    elif [ "${state1}" = 'inactive' ]; then
+      echo "NODERED:OFF"
+    else
+      echo "NODERED:ERROR"
+      err=22 # EINVAL
+    fi
+    ;;
+  '--help')
+    usage
+    err=0
+    ;;
+  *)
+    usage
+    echo "BUG: Unsupported action: ${action}" >&2
+    err=22 # EINVAL
+    ;;
+esac
+exit ${err}
diff --git a/bin/txt_servo b/bin/txt_servo
new file mode 100644
index 0000000000000000000000000000000000000000..c3e3a94d396e5c0cd2cad7d1c19f91ba22ecfb0b
--- /dev/null
+++ b/bin/txt_servo
@@ -0,0 +1,121 @@
+#!/bin/bash
+
+# Usage
+
+servo_min_min=300
+servo_min_max=1100
+servo_min_default=600
+
+servo_max_min=1900
+servo_max_max=2700
+servo_max_default=2400
+
+usage()
+{
+  echo "Usage: sudo txt_servo <operation> <servonum> ..."
+  echo "sudo txt_servo setcalibration <servonum> <min> <max>"
+  echo "sudo txt_servo setmin <servonum> <min> "
+  echo "sudo txt_servo setmax <servonum> <max> "
+  echo "sudo txt_servo getmin <servonum> "
+  echo "sudo txt_servo getmax <servonum> "
+  echo "sudo txt_servo getvalues <servonum> "
+}
+
+# Assigning arguments
+
+operation="${1}"
+servo_num="${2}"
+
+getServoValues()
+{
+    servo_num="${1}"
+    min_val="$(/sbin/fw_printenv -n "servo${servo_num}_min" 2>/dev/null)"
+    if [ ! $? -eq 0 ]
+    then
+        min_val=$servo_min_default
+        /sbin/fw_setenv "servo${servo_num}_min" "${min_val}" 2>/dev/null
+    fi
+
+    max_val="$(/sbin/fw_printenv -n "servo${servo_num}_max" 2>/dev/null)"
+    if [ ! $? -eq 0 ]
+    then
+        max_val=$servo_max_default
+        /sbin/fw_setenv "servo${servo_num}_max" "${max_val}" 2>/dev/null
+    fi
+
+    if [ ! "$min_val" ]
+    then
+        min_val=$servo_min_default
+        /sbin/fw_setenv "servo${servo_num}_min" "${min_val}" 2>/dev/null
+    fi
+    if [ $min_val -gt $servo_min_max ]
+    then
+        min_val=$servo_min_max
+        /sbin/fw_setenv "servo${servo_num}_min" "${min_val}" 2>/dev/null
+    fi
+    if [ $min_val -lt $servo_min_min ]
+    then
+        min_val=$servo_min_min
+        /sbin/fw_setenv "servo${servo_num}_min" "${min_val}" 2>/dev/null
+    fi
+
+    if [ ! "$max_val" ]
+    then
+        max_val=$servo_max_default
+        /sbin/fw_setenv "servo${servo_num}_max" "${max_val}" 2>/dev/null
+    fi
+    if [ $max_val -lt $servo_max_min ]
+    then
+        max_val=$servo_max_min
+        /sbin/fw_setenv "servo${servo_num}_max" "${max_val}" 2>/dev/null
+    fi
+    if [ $max_val -gt $servo_max_max ]
+    then
+        max_val=$servo_max_max
+        /sbin/fw_setenv "servo${servo_num}_max" "${max_val}" 2>/dev/null
+    fi
+
+    echo "{\"servo\":\"$servo_num\",\"min\":\"${min_val}\",\"max\":\"${max_val}\"}" 2>/dev/null || :
+}
+
+case "${operation}" in
+    "init")
+        echo "{"
+        echo "  $(getServoValues 1),"
+        echo "  $(getServoValues 2),"
+        echo "  $(getServoValues 3)"
+        echo "}"
+        ;;
+    "setcalibration")
+        servo_min="${3}"
+        servo_max="${4}"
+        /sbin/fw_setenv "servo${servo_num}_min" "${servo_min}" 2>/dev/null
+        /sbin/fw_setenv "servo${servo_num}_max" "${servo_max}" 2>/dev/null
+        getServoValues "${servo_num}"
+    ;;
+    "setmin")
+        servo_min="${3}"
+        /sbin/fw_setenv "servo${servo_num}_min" "${servo_min}" 2>/dev/null
+        getServoValues "${servo_num}"
+    ;;
+    "setmax")
+        servo_max="${3}"
+        /sbin/fw_setenv "servo${servo_num}_max" "${servo_max}" 2>/dev/null
+        getServoValues "${servo_num}"
+    ;;
+    "getmin")
+        getServoValues "${servo_num}"
+    ;;
+    "getmax")
+        getServoValues "${servo_num}"
+    ;;
+    "getvalues")
+        getServoValues "${servo_num}"
+    ;;
+    *)
+        usage
+        exit 1
+    ;;
+esac
+
+exit 0
diff --git a/bin/txt_update_avahi b/bin/txt_update_avahi
new file mode 100644
index 0000000000000000000000000000000000000000..b1b6cf70eeee8cac85cbe1319bc48393c46a5746
--- /dev/null
+++ b/bin/txt_update_avahi
@@ -0,0 +1,189 @@
+#!/bin/sh
+
+get_domain_search()
+{
+    echo "$(cat /etc/resolv.conf | grep search | grep -v "#" | awk '{print $2}')"
+}
+
+get_hostname()
+{
+    echo "$(hostname)"
+}
+
+get_hostnames()
+{
+    echo "blablub.local"
+    echo "$(get_hostname)"
+    echo "$(get_hostname).local"
+    if [ "$(get_domain_search)" ]; then
+        echo "$(get_hostname).$(get_domain_search)"
+    fi
+}
+
+get_ip_addresses()
+{
+    echo "$(ip -o addr | awk '!/^[0-9]*: ?lo|link\/ether/ {gsub("/", " "); print $4}')"
+}
+
+get_ip_hostnames()
+{
+    IPs="$(get_ip_addresses)"
+    HOSTNAMEs="$(get_hostnames)"
+    for IP in $IPs
+    do
+      for HOSTNAME in $HOSTNAMEs
+      do
+        echo "$IP $HOSTNAME"
+      done
+    done
+}
+
+get_txtapi_version()
+{
+    SW_VERS="$(cat /usr/lib/python3.5/site-packages/txtapi/VERSION | grep "^VERSION_NUM=" | awk -F'=' '{print $2}')"
+    if [ ! "$SW_VERS" ]
+    then
+        echo "unknown"
+    else
+        echo "$SW_VERS"
+    fi
+}
+
+get_swversion_version()
+{
+    SW_VERS="$(cat /slot.raucs | grep "bundle.version" | awk -F"=" '{print $2}')"
+    if [ ! "$SW_VERS" ]
+    then
+        echo "unknown"
+    else
+        echo "$SW_VERS"
+    fi
+}
+
+get_build()
+{
+    SW_VERS="$(cat /slot.raucs | grep "bundle.build" | awk -F"=" '{print $2}')"
+    if [ ! "$SW_VERS" ]
+    then
+        echo "unknown"
+    else
+        echo "$SW_VERS"
+    fi
+}
+
+
+get_build_type()
+{
+    if [ "$(cat /slot.raucs | grep "bundle.description=image-qt-dev")" ]
+    then
+        echo "debug"
+    else
+        echo "release"
+    fi
+}
+
+get_wifi_type()
+{
+    if [ "$(mlanutl mlan0 getdatarate | grep "BW:   20 MHz")" ]
+    then
+        echo "2.4 GHz"
+    elif [ "$(mlanutl mlan0 getdatarate | grep "BW:   40 MHz")" ]
+    then
+        echo "5 GHz"
+    else
+        echo "unknown"
+    fi
+}
+
+get_wifi_essid()
+{
+    essid=""
+    val=$(cat /proc/mwlan/mlan0/info | grep "essid" | sed -e 's|["'\'']||g')
+    if [ "$val" ]
+    then
+        export "$val"
+    fi
+    if [ ! "$essid" ]
+    then
+        echo "unknown"
+    else
+        echo "$essid"
+    fi
+}
+
+update_device_info()
+{
+    SOURCECODE_VERSION="$(get_swversion_version)"
+    TXTAPI_VERSION="$(get_txtapi_version)"
+    BUILD_TYPE="$(get_build_type)"
+    BUILD_NUM="$(get_build)"
+    WLAN_TYPE="$(get_wifi_type)"
+    WLAN_ESSID="$(get_wifi_essid)"
+cat << EOF > /etc/avahi/services/device-info.service
+<?xml version="1.0" standalone="no"?><!--*-nxml-*-->
+<service-group>
+    <name replace-wildcards="yes">%h</name>
+    <service>
+        <type>_device-info._tcp</type>
+        <port>0</port>
+        <txt-record>model=TXT40</txt-record>
+        <txt-record>sw-version=${SOURCECODE_VERSION}</txt-record>
+        <txt-record>txtapi-version=${TXTAPI_VERSION}</txt-record>
+        <txt-record>build-type=${BUILD_TYPE}</txt-record>
+        <txt-record>build=${BUILD_NUM}</txt-record>
+        <txt-record>wlan-essid=${WLAN_ESSID}</txt-record>
+        <txt-record>wlan-type=${WLAN_TYPE}</txt-record>
+    </service>
+</service-group>
+EOF
+    chmod 644 /etc/avahi/services/device-info.service
+}
+
+update_fischertechnik_txt40()
+{
+    SOURCECODE_VERSION="$(get_swversion_version)"
+    TXTAPI_VERSION="$(get_txtapi_version)"
+    BUILD_TYPE="$(get_build_type)"
+    BUILD_NUM="$(get_build)"
+    WLAN_TYPE="$(get_wifi_type)"
+    WLAN_ESSID="$(get_wifi_essid)"
+cat << EOF > /etc/avahi/services/fischertechnik-txt40.service
+<?xml version="1.0" standalone="no"?><!--*-nxml-*-->
+<service-group>
+    <name replace-wildcards="yes">%h</name>
+    <service>
+        <type>_fischertechnik-txt40._tcp</type>
+        <port>80</port>
+        <txt-record>model=TXT40</txt-record>
+        <txt-record>sw-version=${SOURCECODE_VERSION}</txt-record>
+        <txt-record>txtapi-version=${TXTAPI_VERSION}</txt-record>
+        <txt-record>build-type=${BUILD_TYPE}</txt-record>
+        <txt-record>build=${BUILD_NUM}</txt-record>
+        <txt-record>wlan-essid=${WLAN_ESSID}</txt-record>
+        <txt-record>wlan-type=${WLAN_TYPE}</txt-record>
+    </service>
+</service-group>
+EOF
+    chmod 644 /etc/avahi/services/fischertechnik-txt40.service
+}
+
+update_avahi()
+{
+    update_device_info
+    update_fischertechnik_txt40
+    avahi-daemon --reload
+}
+
+sleep 10
+update_avahi
+if [ "$1" = "restart-avahi" ]
+then
+    systemctl restart avahi-daemon || true
+    sleep 5
+fi
+
+avahi-daemon --check
+if [ "$?" != "0" ]
+then
+    systemctl start avahi-daemon || true
+fi
diff --git a/bin/txt_vnc b/bin/txt_vnc
new file mode 100755
index 0000000000000000000000000000000000000000..1dc405870225d0883eadeadcc8600e486ba5aab6
--- /dev/null
+++ b/bin/txt_vnc
@@ -0,0 +1,75 @@
+#!/bin/sh
+# Script-helper to control vnc server service
+#
+#  Copyright (c) 2023 Manuel Schreiner, Accso. All rights reserved.
+#
+#  SPDX-License-Identifier: Apache-2.0
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+# Usage
+
+usage()
+{
+  echo "Usage: sudo txt_vnc <on|off|status>"
+}
+
+# Assigning arguments
+
+action="${1}"
+
+# Setttings
+
+vnc_service='framebuffer-vncserver'
+vnc_sessions='framebuffer-vncserver@*.service'
+
+# Arguments verification
+
+. /usr/share/txt2-utils/txt_aux_functions
+
+# Main
+
+check_nargs "$#" 1
+case "${action}" in
+  'on')
+    err=0
+    /bin/systemctl start "${vnc_service}" || err=$?
+    ;;
+  'off')
+    err=0
+    /bin/systemctl kill "${vnc_sessions}" || err=$?
+    /bin/systemctl stop "${vnc_service}" || err=$?
+    ;;
+  'status')
+    state1="$(/bin/systemctl is-active "${vnc_service}")"
+    err=0
+    if [ "${state1}" = 'active' ]; then
+      echo "VNC:ON"
+    elif [ "${state1}" = 'inactive' ]; then
+      echo "VNC:OFF"
+    else
+      echo "VNC:ERROR"
+      err=22 # EINVAL
+    fi
+    ;;
+  '--help')
+    usage
+    err=0
+    ;;
+  *)
+    usage
+    echo "BUG: Unsupported action: ${action}" >&2
+    err=22 # EINVAL
+    ;;
+esac
+exit ${err}
diff --git a/bin/txt_wifi_setup b/bin/txt_wifi_setup
index 30f9cb959b3f80be2ba7bd16ff05485bc247e4b7..c38dc80ba38d30eb26dc24e1ea9571d788f23b4d 100755
--- a/bin/txt_wifi_setup
+++ b/bin/txt_wifi_setup
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 # Main script to configure WiFi settings and start WiFi
 #
 #  Copyright (c) 2020 RTSoft. All rights reserved.
@@ -26,9 +26,12 @@ usage()
   echo "       txt_wifi_setup start point {raw|hex|esc} <ssid> {raw <password>|psk <key>|none} <channel>"
   echo "       txt_wifi_setup stop [client|point]"
   echo "       txt_wifi_setup scan"
+  echo "       txt_wifi_setup scan_results"
   echo "       txt_wifi_setup status"
   echo "       txt_wifi_setup ping <host>"
   echo "       txt_wifi_setup init"
+  echo "       txt_wifi_setup mmcspeed <mmc speed in Hz>"
+  echo "       txt_wifi_setup netdev"
 }
 
 # Assigning arguments
@@ -68,16 +71,29 @@ parse_args()
     'ping')
       host="${2}"
       ;;
+    'mmcspeed')
+      mmcspeed="${2}"
+      ;;
   esac
 }
 
 # Settings
 
 iface_client=mlan0
-iface_client_metric=100
-iface_client_timeout=10 # 10 seconds to establish the link
+if [ "$(lsusb | grep "RT5370")" ]
+then
+    flags=$(cat /sys/class/net/mlan0/flags)
+    if [ "${flags}" = "0x1003" ]
+    then
+      /usr/bin/sudo -n /sbin/ifconfig mlan0 down
+    fi
+    iface_client=wlan0
+fi
+
+iface_client_metric=1
+iface_client_timeout=12 # 12 seconds to establish the link
 iface_apoint=uap0
-iface_apoint_timeout=10 # 10 seconds to establish the link
+iface_apoint_timeout=12 # 12 seconds to establish the link
 
 temp_conf_dir=/tmp/txt2-utils
 hostap_conf_work="${temp_conf_dir}/hostapd.conf"
@@ -186,13 +202,21 @@ check_args()
           ;;
       esac
       ;;
-    'scan'|'status'|'init')
+    'scan'|'scan_results'|'status'|'init')
       check_nargs "$#" 1
       ;;
     'ping')
       check_nargs "$#" 2
       check_notempty "${host}"
       ;;
+    'mmcspeed')
+      check_nargs "$#" 2
+      check_notempty "${mmcspeed}"
+      ;;
+    'recovery')
+      ;;
+    'netdev')
+      ;;
     '--help')
       usage
       exit 0
@@ -205,12 +229,102 @@ check_args()
   esac
 }
 
+reset_mmc()
+{
+    echo 48004000.sdmmc > /sys/bus/amba/drivers/mmci-pl18x/unbind
+    sleep 5
+    echo 48004000.sdmmc > /sys/bus/amba/drivers/mmci-pl18x/bind
+}
+get_mmc_dev()
+{
+    mmc_dev="$(ls /sys/module/sd8xxx/drivers/sdio\:wlan_sdio | grep mmc)"
+    echo "$mmc_dev"
+}
+
+get_mmc_controller()
+{
+    mmc_ctrl="$(get_mmc_dev | awk -F":" '{print $1}')"
+    echo "$mmc_ctrl"
+}
+
+get_mmc_speed()
+{
+    mmc_ctrl=$(get_mmc_controller)
+    if [ ! "$mmc_ctrl" ]
+    then
+        echo "ERROR: no valid controller found"
+        return
+    fi
+    cat	/sys/kernel/debug/${mmc_ctrl}/clock
+}
+
+set_mmc_speed()
+{
+    mmc_speed="$1"
+    mmc_ctrl=$(get_mmc_controller)
+    if [ ! "$mmc_ctrl" ]
+    then
+        echo "ERROR: no valid controller found"
+        return
+    fi
+
+    case "${mmc_speed}" in
+      "50MHz"|"50000000")
+        echo 50000000 > /sys/kernel/debug/${mmc_ctrl}/clock
+      ;;
+      "25MHz"|"25000000")
+        echo 25000000 > /sys/kernel/debug/${mmc_ctrl}/clock
+      ;;
+      "12,5MHz"|"12500000")
+        echo 12500000 > /sys/kernel/debug/${mmc_ctrl}/clock
+      ;;
+      *)
+        echo "ERROR: Speed is not supported"
+      ;;
+    esac
+    cat	/sys/kernel/debug/${mmc_ctrl}/ios | grep "actual clock"
+}
+
+get_gateway()
+{
+    echo "$(netstat -r -n | grep "${iface_client}" | grep "UG" | awk '{print $2}')"
+}
+
+wifi_recovery()
+{
+    /usr/bin/sudo -n /usr/bin/killall -q dhcpcd  || true
+    /usr/bin/sudo -n /usr/bin/killall -q wpa_supplicant || true
+    /usr/bin/sudo -n /usr/bin/killall -q hostapd || true
+    /usr/bin/sudo -n /sbin/ifconfig ${iface_client} down || true
+    /usr/bin/sudo -n /sbin/ifconfig ${iface_apoint} down || true
+    /usr/bin/sudo -n /sbin/ip addr flush dev "${iface_client}"
+    for (( i = 0; i <= 30; i++ ))
+    do
+        /usr/bin/sudo -n /sbin/rmmod sd8xxx 2> /dev/null
+        lsmod 2>&1 | grep sd8xxx > /dev/null
+        if [ ! $? -eq 0 ]; then
+            break
+        fi
+        sleep 1
+    done
+    /usr/bin/sudo -n /sbin/rmmod mlan || true
+    sleep 5
+    /usr/bin/sudo -n /sbin/modprobe mlan || true
+    /usr/bin/sudo -n /sbin/modprobe sd8xxx || true
+    /usr/bin/sudo -n /usr/bin/killall -q wpa_supplicant || true
+    /usr/bin/sudo -n /usr/bin/killall -q hostapd || true
+}
+
 check_client_iface()
 {
   if [ ! -L "/sys/class/net/${iface_client}" ]
   then
     echo "BUG: WLAN interface is not found: ${iface_client}" >&2
-    exit 19 # ENODEV
+    wifi_recovery
+    if [ ! -L "/sys/class/net/${iface_client}" ]
+    then
+      exit 19 # ENODEV
+    fi
   fi
 }
 
@@ -219,7 +333,11 @@ check_point_iface()
   if [ ! -L "/sys/class/net/${iface_apoint}" ]
   then
     echo "BUG: WLAN AP interface is not found: ${iface_apoint}" >&2
-    exit 19 # ENODEV
+    wifi_recovery
+    if [ ! -L "/sys/class/net/${iface_client}" ]
+    then
+      exit 19 # ENODEV
+    fi
   fi
 }
 
@@ -238,7 +356,6 @@ make_wifi_client_config()
   else
     # Write PSK to config
     script="s/^${spaces}key_mgmt=.*$/key_mgmt=WPA-PSK/;s/^${spaces}psk=.*$/psk=${psk}/;"
-    ""
   fi
 
   /bin/sed -e "s/^${spaces}ssid=.*$/$(sed_escape "${ssid_expr}")/" \
@@ -265,6 +382,21 @@ make_access_point_config()
            "${hostap_conf_template}"
 }
 
+do_set_mmc_speed()
+{
+    set_mmc_speed "${mmcspeed}"
+}
+
+do_get_mmc_speed()
+{
+    get_mmc_speed
+}
+
+do_get_gateway()
+{
+    get_gateway
+}
+
 do_start_client()
 {
   check_client_iface
@@ -296,33 +428,36 @@ do_start_client()
 
   /usr/bin/sudo -n /sbin/ifconfig "${iface_client}" up
   /usr/bin/sudo -n /usr/sbin/iw dev "${iface_client}" set power_save off
-
+  
+  /usr/bin/sudo -n /usr/sbin/wpa_cli "-i${iface_client}" flush
   /usr/bin/sudo -n /usr/sbin/wpa_supplicant -B "-i${iface_client}" "-c${wpasup_conf_work}"
-
+  /usr/bin/sudo -n /usr/sbin/wpa_cli "-i${iface_client}" sta_autoconnect 1
+  
   if [ "${ip_mode}" = 'static' ]; then
     /usr/bin/sudo -n /sbin/ifconfig "${iface_client}" "${ip}" netmask "${netmask}"
     if [ -n "${gateway}" ]; then
-      /usr/bin/sudo -n /sbin/route add default gw "${gateway}" dev "${iface_client}"
+      /usr/bin/sudo -n /sbin/route add default gw "${gateway}" metric "${iface_client_metric}" dev "${iface_client}"
     fi
     if [ -n "${dns}" ]; then
       # Although mlan0 is out of SystemD management, we can still use resolvectl
       /usr/bin/sudo -n /usr/share/txt2-utils/txt_set_dns "${iface_client}" "${dns}"
       # no need to reset dns otherwise, as we already perfored do_stop_client before do_start_client
     fi
-
-    # Let system to establish the link before script exits
-    while [ "${i:-0}" -lt "${iface_client_timeout}" ]; do
-      status_client=$(/bin/cat "/sys/class/net/${iface_client}/operstate")
-      if [ "${status_client}" = 'up' ]; then
-        break
-      fi
-      /bin/sleep 1
-      i=$((i+1))
-    done
   else
-    /usr/bin/sudo -n /usr/sbin/dhcpcd "${iface_client}" -m "${iface_client_metric}"
+    /usr/bin/sudo -n /usr/sbin/dhcpcd -b -t 0 -m "${iface_client_metric}" "${iface_client}"
     # DHCP client software manages DNS setup via resolvconf, `resolvectl revert` is done in do_stop_client
   fi
+
+  # Let system to establish the link before script exits
+  while [ "${i:-0}" -lt "${iface_client_timeout}" ]; do
+    status_client=$(/bin/cat "/sys/class/net/${iface_client}/operstate")
+    if [ "${status_client}" = 'up' ]; then
+      break
+    fi
+    /bin/sleep 1
+    i=$((i+1))
+  done
+  sudo -n /usr/sbin/txt_update_avahi "restart-avahi" || true
 }
 
 do_stop_client()
@@ -409,20 +544,132 @@ do_stop_all()
   do_stop_access_point
 }
 
+check_host_online()
+{
+  host="$1"
+  ret=1
+  for port in 53 80 443 21 22 23
+  do
+    timeout 2 bash -c "</dev/tcp/${host}/${port}" 2&> /dev/null > /dev/null
+    if [ $? -eq 0 ]
+    then
+      ret=0
+      return $ret
+      break
+    fi
+  done
+  for (( i = 0; i <= 15; i++ ))
+  do
+    /bin/ping -c1 -W5 "$host" >&2 > /dev/null
+    if [ $? -eq 0 ]
+    then
+      ret=0
+      return $ret
+      break
+    fi
+    sleep 1
+  done
+  return $ret
+}
+
+try_command()
+{
+    tries=$1
+    sleep_between=$2
+    shift
+    shift
+    cmd="$@"
+    res=1
+    while [ ! $res -eq 0 ] && [ $tries -gt 0 ]
+    do
+        $cmd
+        res="$?"
+        tries=$((tries - 1))
+        if [ ! $res -eq 0 ]
+       	then
+          sleep ${sleep_between}
+       	fi
+    done
+    return $res
+}
+
+try_command_sudo()
+{
+    tries=$1
+    sleep_between=$2
+    shift
+    shift
+    cmd="$@"
+    res=1
+    while [ ! $res -eq 0 ] && [ $tries -gt 0 ]
+    do
+        /usr/bin/sudo -n $cmd
+        res="$?"
+        tries=$((tries - 1))
+        if [ ! $res -eq 0 ]
+       	then
+          sleep ${sleep_between}
+       	fi
+    done
+    return $res
+}
+
+do_scan_results()
+{
+  check_client_iface
+  try_command_sudo 3 3 /usr/sbin/wpa_cli "-i${iface_client}" scan_result
+}
+
 do_scan()
 {
   check_client_iface
+
+
+  # check if gateway is reachable - works only if wpa_supplicant is connected
+  if [ "$(pidof wpa_supplicant)" ]
+  then
+    gw="$(get_gateway)"
+    if [ "$gw" ] 
+    then
+      try_command 2 1 /bin/ping -I"${iface_client}" -c1 -W1 "$gw" >&2 > /dev/null
+      if [ ! $? -eq 0 ]
+      then
+        try_command 2 1 /bin/ping -I"${iface_client}" -c1 -W1 "8.8.8.8" >&2 > /dev/null
+        if [ ! $? -eq 0 ]
+        then
+          check_host_online "$gw"
+          if [ ! $? -eq 0 ]
+          then
+            wifi_recovery
+            sleep 5
+          fi
+        fi
+      fi
+    fi
+  fi
+
   flags=$(/bin/cat "/sys/class/net/${iface_client}/flags")
   if [ "${flags}" = "0x1002" ]
   then
-    /usr/bin/sudo -n /sbin/ifconfig "${iface_client}" up
+    /usr/bin/sudo -n /sbin/ifconfig "${iface_client}" up 2> /dev/null > /dev/null
+  fi
+  
+  if [ -f "/usr/bin/mlanutl" ] && [ "${iface_client}" == "mlan0" ]
+  then
+    /usr/bin/sudo -n /usr/bin/mlanutl "${iface_client}" setuserscan
+  else
+    # Fallback if mlanutl does not exist: WPA CLI requires a running wpa_supplicant, if not running use iw
+    if [ "$(pidof wpa_supplicant)" ]
+    then
+      /usr/bin/sudo -n /usr/sbin/wpa_cli "-i${iface_client}" scan 2> /dev/null
+    else
+      try_command_sudo 3 3 /usr/sbin/iw dev "${iface_client}" scan flush
+    fi
   fi
-
-  /usr/bin/sudo -n /usr/sbin/iw dev "${iface_client}" scan
 
   if [ "${flags}" = "0x1002" ]
   then
-    /usr/bin/sudo -n /sbin/ifconfig "${iface_client}" down
+    /usr/bin/sudo -n /sbin/ifconfig "${iface_client}" down 2> /dev/null > /dev/null
   fi
 }
 
@@ -432,7 +679,7 @@ do_status_client()
   status_client=$(/bin/cat "/sys/class/net/${iface_client}/operstate")
   if [ "${flags_client}" = '0x1003' ]; then
     # Client interface is up
-    if [ "${status_client}" = 'up' ]; then
+    if [ "${status_client}" = 'up' ] && /bin/pidof wpa_supplicant >/dev/null; then
       # Interface fully configured, link ready
       echo 'CLIENT:ON'
       echo "CLIENT_IP:$(expr match "$(/sbin/ip -4 address show dev "${iface_client}")" '.*inet \([0-9.]*/[0-9]*\)')"
@@ -452,7 +699,7 @@ do_status_access_point()
     status_apoint=$(/bin/cat "/sys/class/net/${iface_apoint}/operstate")
     if [ "${flags_apoint}" = '0x1003' ]; then
       # Access point interface is up
-      if [ "${status_apoint}" = 'up' ]; then
+      if [ "${status_apoint}" = 'up' ] && /bin/pidof hostapd >/dev/null; then
         # Interface fully configured, link ready
         echo 'POINT:ON'
         echo "POINT_IP:$(expr match "$(/sbin/ip -4 address show dev "${iface_apoint}")" '.*inet \([0-9.]*/[0-9]*\)')"
@@ -478,7 +725,7 @@ do_status()
   status_client=$(/bin/cat "/sys/class/net/${iface_client}/operstate")
   if [ "${flags_client}" = '0x1003' ]; then
     # Client interface is up
-    if [ "${status_client}" = 'up' ]; then
+    if [ "${status_client}" = 'up' ] && /bin/pidof wpa_supplicant >/dev/null; then
       # Interface fully configured, link ready
       echo 'CLIENT:ON'
       echo "CLIENT_IP:$(expr match "$(/sbin/ip -4 address show dev "${iface_client}")" '.*inet \([0-9.]*/[0-9]*\)')"
@@ -492,7 +739,7 @@ do_status()
     status_apoint=$(/bin/cat "/sys/class/net/${iface_apoint}/operstate")
     if [ "${flags_apoint}" = '0x1003' ]; then
       # Access point interface is up
-      if [ "${status_apoint}" = 'up' ]; then
+      if [ "${status_apoint}" = 'up' ] && /bin/pidof hostapd >/dev/null; then
         # Interface fully configured, link ready
         echo 'POINT:ON'
         echo "POINT_IP:$(expr match "$(/sbin/ip -4 address show dev "${iface_apoint}")" '.*inet \([0-9.]*/[0-9]*\)')"
@@ -508,10 +755,20 @@ do_status()
 
 do_ping()
 {
-  if /bin/ping -I"${iface_client}" -c1 -W2 "${host}" >&2; then
+  if /bin/ping -I"${iface_client}" -c1 -W2 "${host}" >&2 > /dev/null; then
     echo 'PING:OK'
   else
-    echo 'PING:FAILED'
+    sleep 1
+    if /bin/ping -I"${iface_client}" -c1 -W4 "${host}" >&2 > /dev/null; then
+        echo 'PING:OK'
+    else
+        sleep 1
+        if /bin/ping -I"${iface_client}" -c1 -W4 "${host}" >&2 > /dev/null; then
+            echo 'PING:OK'
+        else
+            echo 'PING:FAILED'
+        fi
+    fi
   fi
 }
 
@@ -528,6 +785,11 @@ do_init()
   echo 'INIT:OK'
 }
 
+get_active_netdev()
+{
+    echo "NETDEV:$iface_client"
+}
+
 # Main
 
 # - check arguments
@@ -570,12 +832,24 @@ case "${action}" in
   'scan')
     do_scan
     ;;
+  'scan_results')
+    do_scan_results
+    ;;
   'status')
     do_status
     ;;
   'ping')
     do_ping
     ;;
+  'mmcspeed')
+    do_set_mmc_speed
+    ;;
+  'recovery')
+    wifi_recovery
+    ;;
+  'netdev')
+    get_active_netdev
+    ;;
   'init')
     do_init
     ;;
diff --git a/src/txt_hostname_publisher.c b/src/txt_hostname_publisher.c
index e8ac2581e5cbf37cc4be7ac7e0953d4b69f63a18..4d60b131dda8505432ba7401a6dc109e5c5a7397 100644
--- a/src/txt_hostname_publisher.c
+++ b/src/txt_hostname_publisher.c
@@ -40,6 +40,8 @@
 #include <avahi-client/client.h>
 #include <avahi-client/publish.h>
 
+char local_hostname[512] = "txt40.local";
+
 static const char *aliases[] = {
     "txt40.local",
     NULL
@@ -73,6 +75,19 @@ struct address_entry {
 
 static struct address_entry *addresses = NULL;
 
+static void update_aliases()
+{
+   FILE *fptr;
+   fptr = fopen("/etc/hostname", "r");
+   if(fptr != NULL) 
+   {
+       fgets(local_hostname,sizeof(local_hostname),fptr);
+       fclose(fptr);
+       local_hostname[strlen(local_hostname)-1] = 0;
+       strcat(local_hostname,".local");
+   }
+}
+
 static void thread_quit()
 {
     struct mnl_socket *s = mnl_sock;
@@ -136,8 +151,8 @@ static int register_hostnames(AvahiClient *c)
     struct alias_entry **alias;
     int ret;
 
+    update_aliases();
     for (address = addresses; address != NULL; address = address->next) {
-
         for (alias = &address->aliases, name = aliases; *name != NULL;
              ++name, alias = &(*alias)->next) {
 
@@ -205,6 +220,7 @@ static void client_cb(AvahiClient *c, AvahiClientState state,
     case AVAHI_CLIENT_FAILURE:
         if (avahi_client_errno(c) == AVAHI_ERR_DISCONNECTED) {
             fprintf(stderr, "%s: Disconnected, reconnecting...\n", __func__);
+            update_aliases();
             for (address = addresses; address != NULL;
                                       address = address->next) {
                 for (alias = address->aliases; alias != NULL;
@@ -375,6 +391,7 @@ static int address_cb(const struct nlmsghdr *msg, void *data)
             for (address = &addresses; *address != NULL;) {
                 if (strcasecmp((*address)->ip_addr, ip_addr) == 0
                         /* && (*address)->index == ifa->ifa_index */) {
+                    update_aliases();
                     for (alias = (*address)->aliases; alias != NULL;) {
                         if (alias->group != NULL) {
                             ret = avahi_entry_group_reset(alias->group);
@@ -545,6 +562,7 @@ cleanup:
     }
 
     for (address = addresses; address != NULL;) {
+        update_aliases();
         for (alias = address->aliases; alias != NULL;) {
             a = alias;
             alias = alias->next;