0

I took this script somewhere over the internet, that automatically changes to a better wifi network. It was working fine till a few weeks ago. I modified it a little to try to find out where the problem was, and it seems that the for loop isn't iterating properly through the available wifi networks list. Any ideas will be appreciated. Here's the script:

#!/bin/bash
threshold=10

# Lets do a scan first
sudo /usr/bin/nmcli -t -f ssid,signal,rate,in-use dev wifi rescan

# And get the list of known networks
known_networks_info=$(/usr/bin/nmcli -t -f name connection show | sed -e 's/^Auto //g')
echo "knowm networks"
echo $known_networks_info

# What's the current network, yet?
current_network_name=$(/usr/bin/nmcli -t -f ssid,signal,rate,in-use dev wifi list | grep ':\*' | cut -d ':' -f1)
current_network_strength=$(/usr/bin/nmcli -t -f ssid,signal,rate,in-use dev wifi list | grep ':\*' | cut -d ':' -f2)
echo "current net $current_network_name, strength $current_network_strength"

# Now see if we have a better network to switch to. Networks are sorted by signal strength so there's no need to check them all if the first signal's strength is not higher than current network's strength + threshold.
network_list=$(/usr/bin/nmcli -t -f ssid,signal,rate,in-use dev wifi list | grep -v $current_network_name | sort -nr -k2 -t':')
echo "network list"
echo $network_list
typeset -p network_list
for network in "$network_list" ; do
        network_name=$(echo $network | cut -d ':' -f1)
        network_strength=$(echo $network | cut -d ':' -f2)
        echo "net $network_name, strength $network_strength"
        # if [[ "$network_name" == "" ]]; then continue ; fi # MESH hotspots may appear with an non existent SSID so we skip them 
        # if [[ "$known_networks_info" == *"$network_name"* ]]; then
        #         if [ $network_strength -ge $(($current_network_strength + $threshold)) ]; then
        #                 notification="Switching to network $network_name that has a better signal ($network_strength>$(($current_network_strength + $threshold)))"
        #                 echo $notification
        #                 notify-send "$notification"
        #                 sudo /usr/bin/nmcli device wifi connect $network_name
        #         else
        #                 notification="Network $network_name is well known but its signal's strength is not worth switching"
        #                 echo $notification
        #                 notify-send "$notification"
        #                 exit 0
        #         fi
        # fi
done

This is an output of the script above:

knowm networks
Amara Amara_EXT Kira Kira_5g Kira_5G Kira_5GEXT Kira_EXT RedmiGao RedmiKira VTR-2201458 VTR-2201458_EXT VTR-2201458_EXT2 VTR-9329907 VTR-9329907_EXT Wired connection 1
current net Amara, strength 82
network list
HUAWEI-B2368-472705:80:270 Mbit/s: HUAWEI-B2368-5G-472706:70:270 Mbit/s: Mi 10T Pro:62:130 Mbit/s: Irene.:50:130 Mbit/s: C L E Y A 5G:32:540 Mbit/s: C L E Y A:32:540 Mbit/s: Irene.:25:540 Mbit/s: Irene. 5G:22:540 Mbit/s: Mateo:15:130 Mbit/s:
declare -- network_list="HUAWEI-B2368-472705:80:270 Mbit/s: 
HUAWEI-B2368-5G-472706:70:270 Mbit/s: 
Mi 10T Pro:62:130 Mbit/s: 
Irene.:50:130 Mbit/s: 
C L E Y A 5G:32:540 Mbit/s: 
C L E Y A:32:540 Mbit/s: 
Irene.:25:540 Mbit/s: 
Irene. 5G:22:540 Mbit/s: 
Mateo:15:130 Mbit/s: "
net HUAWEI-B2368-472705, strength 80
6
  • primary issue is the for loop is breaking $network_list on white space, but can't tell from this example if this is due to your modified output of the nmcli output or the missing double quotes in the first for loop; couple suggestions: add typeset -p network_list before the main for loop (so we can see what's actually in $network_list; try adding double quotes in the first for loop, eg, for network in "$network_list" (this should Commented Jun 16, 2021 at 19:01
  • @markp-fuso thanks for your comments. I updated the question according to your first one, added the corresponding output. I'm trying to figure out how to do your second comment. Commented Jun 16, 2021 at 19:28
  • ignore my 2nd comment (now deleted) ... I was getting ahead of myself; consider replacing the outer for loop with while read -r network; do ... ; done <<< "${network_list}" Commented Jun 16, 2021 at 19:33
  • 1
    @markp-fuso thanks, that worked, I will post an answer with your solution Commented Jun 16, 2021 at 19:41
  • 2
    Actually, I'd recommend using while IFS=: read -r network_name network_strength network_speed; do ... and skip using cut to extract those fields. Commented Jun 16, 2021 at 19:43

1 Answer 1

1

Thanks to @markp-fuso and @GordonDavisson for the comments, here is a fixed script:

#!/bin/bash
threshold=10

# Lets do a scan first
sudo /usr/bin/nmcli -t -f ssid,signal,in-use dev wifi rescan

# And get the list of known networks
known_networks_info=$(/usr/bin/nmcli -t -f name connection show | sed -e 's/^Auto //g')
echo "knowm networks"
echo $known_networks_info

# What's the current network?
current_network_name=$(/usr/bin/nmcli -t -f ssid,signal,rate,in-use dev wifi list | grep ':\*' | cut -d ':' -f1)
current_network_strength=$(/usr/bin/nmcli -t -f ssid,signal,rate,in-use dev wifi list | grep ':\*' | cut -d ':' -f2)
echo "current net $current_network_name, strength $current_network_strength"

# Now see if we have a better network to switch to. Networks are sorted by signal strength so there's no need to check them all if the first signal's strength is not higher than current network's strength + threshold.
network_list=$(/usr/bin/nmcli -t -f ssid,signal,rate,in-use dev wifi list | grep -wv $current_network_name | sort -nr -k2 -t':')
echo "network list"
echo $network_list
echo "checking each network"
while IFS=: read -r network_name network_strength network_rate; do 
        echo "net $network_name, strength $network_strength"
        if [[ "$network_name" == "" ]]; then continue ; fi # MESH hotspots may appear with an non existent SSID so we skip them 
        if [[ "$known_networks_info" == *"$network_name"* ]]; then
                if [ $network_strength -ge $(($current_network_strength + $threshold)) ]; then
                        notification="Switching to network $network_name that has a better signal ($network_strength>$(($current_network_strength + $threshold)))"
                        echo $notification
                        notify-send "$notification"
                        sudo /usr/bin/nmcli device wifi connect $network_name
                else
                        notification="Network $network_name is well known but its signal's strength is not worth switching"
                        echo $notification
                        notify-send "$notification"
                fi
                exit 0
        fi
done <<< "${network_list}"
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.