8

I have a Raspberry Pi 3B running Raspbian Lite Stretch (2018-03-13).

I have an IoT device that broadcasts an AP. I want my RPi to join this AP whenever it is available (i.e., the IoT device is on). But when the AP is not available, I want it to fall back to connecting to my home infrastructure network.

I've configured the networks in the wpa_supplicant config, and assigned a priority of 1000 to the IoT network; if I turn the Raspberry Pi on while the IoT network is broadcasting, it correctly connects to it. When the IoT device goes off, the Raspberry Pi switches to the home network.

However, when the IoT device turns on after the RPi, the RPi does not automatically leave the home network and associate to the IoT device's network.

I'm OK with having to kick off the switch through a cron job or on some other trigger.

Doesn't work: wpa_cli select_network

The first technique I've tried is simply using wpa_cli select_network to switch manually. After running it, list_networks output changes to have this [DISABLED]/[CURRENT] indicator. However, it does not actually change networks.

Selected interface 'p2p-dev-wlan0'
network id / ssid / bssid / flags
0   HomeNetwork any [DISABLED]
1   IoTDevice   any [CURRENT]

I've also tried using wpa_cli reconnect and wpa_cli reassociate but these don't do anything. wpa_cli disconnect also does nothing, and wpa_cli disassociate [BSSID] just reports failure.

Doesn't work: iwconfig

$ sudo iwconfig wlan0 essid "IoTDevice"
Error for wireless request "Set ESSID" (8B1A) :
    SET failed on device wlan0 ; Operation already in progress.

Doesn't work: iw

$ sudo iw wlan0 connect IoTDevice
command failed: Operation already in progress (-114)

Not supported anymore, presumably: wpa-roam

Many guides suggest putting the device into wpa-roam mode, but the information on how to do so is out of date; all the guides reference /etc/network/interfaces, which seems to be virtually blank since the switch to dhcpcd.

Does work, but sucks: Nuking dhcpcd

Other people also express frustration with difficulty restarting wpa_supplicant short of blowing away dhcpcd each time. But when I do this, it does switch to the higher priority network if available.

I've written an answer that periodically scans for the desired network and kills dhcpcd when it's found; this works, but it is a very heavy-handed solution.

Since I can change networks just fine when the associated AP goes down without killing any processes, I shouldn't need to do this.


I'm trying to avoid cargo cult answers that involve flipping interfaces on and off, killing processes and anointing the board with sacred oils. How is switching networks really supposed to work?

5
  • If you want any helpful answers I suggest you provide some information, starting with which OS, what you actually tried, and avoid emotive phrases like " blowing away dhcpcd" and say what commend this may refer to.
    – Milliways
    Commented Mar 28, 2018 at 7:17
  • 1
    The OS, Raspbian Lite 4.9, is in the first sentence. The linked answer about dhcpcd includes the commands to kill dhcpcd but I have also added it to my post.
    – rgov
    Commented Mar 28, 2018 at 7:24
  • Post OS in a tag - don't expect people to follow links, and guess what you did. There is No such thing as "Raspbian Lite 4.9"
    – Milliways
    Commented Mar 28, 2018 at 7:28
  • What happens if you upgrade the OS to RaspiOS Lite (2022-04-04) and try your wpa_cli, iwconfig and wpa-roam stuff again? Uninstalling dhcpcd will have no effect other than breaking all networking on your RPi.
    – Dougie
    Commented Apr 8, 2022 at 20:35
  • Something else that may be relevant to some who are finding this question (but I don't know if it's applicable in Raspbian, so not making an answer out of it) is nmcli - It's what worked for me to manually switch between available networks on an Ubuntu system. (wpa_cli was only showing one in list_networks, even after a scan produced scan_results showing various others -- so I couldn't figure out how to switch with wpa_cli, but nmcli con up <networkname> worked for me.)
    – lindes
    Commented Jan 19, 2023 at 17:43

3 Answers 3

8

If you simply call wpa_cli without specifying the Interface, by default your raspbian stretch uses the interface 'p2p-dev-wlan0', as I can see in the output you posted.

Try the manual switching with wpa_cli by specifying the Interface (assuming that wlan0 is your regular wireless Interface, you want to use to connect to the Access point):

wpa_cli -i wlan0 select_network

1
  • 1
    Thanks for pointing out that the default interface should be specified by -i! That's the key point to solve this problem.
    – Huan
    Commented Aug 31, 2020 at 11:17
2

I'm not happy with this solution, but it does work.

This script will scan for the desired network, and if it is found, it will restart dhcpcd. This disconnects from the current network and then connects to the highest priority network (as configured in wpa_supplicant.conf).

#!/bin/sh
if iwlist wlan0 scan | grep -q "$1"; then
  logger Network "$1" is available, switching
  systemctl restart dhcpcd
fi

Note that iwlist lies about scanning if it is not invoked as root; it will just spit out the details for the current network. Because Linux networking isn't full of enough pitfalls, I guess.

We can save this file in /usr/bin/switch-network-if-available.sh and then set up a cronjob to execute it every minute:

* * * * * root /usr/bin/switch-network-if-available.sh IoTDevice
1
  • Seems the main problem is to switch a wifi connection on the same interface wlan0. Is it an option to have separate interfaces wlan0 and wlan1 for each wifi and let bonding do its work with fail over? Then you can specify what interface should be used when available.
    – Ingo
    Commented Mar 28, 2018 at 10:36
2

This should do what you need using the single wlan0 interface built into your Pi 3. I've tested this on my RPi 3B+; it works for my 2 WiFi APs. I've found it switches quickly as it does not require re-starting any services. You may wish to do some reading (see REFERENCES below) before you begin. The procedure is outlined below in two steps:

Step 1: create/edit wpa_supplicant.conf:

Declare both networks in /etc/wpa_supplicant/wpa_supplicant.conf. You didn't show your wpa_supplicant.conf file, so I've created this one to serve as an example. Be sure to change the country=GB line and network parameters to reflect your situation:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

country=GB

network={
   ssid="MySSID1"
   psk="mypasswd1"
}

network={
   ssid="MySSID2"
   psk="mypasswd2"
}

Step 2: switch networks with wpa_cli:

Use wpa_cli in its interactive mode below, but know that all of these commands may be written as stand-alone commands, suitable for scripting. Lines beginning with # are explanatory comments - not part of the wpa_cli dialogue, and > is the wpa_cli command prompt in interactive mode:

$ wpa_cli 

#  ... # preliminaries...

> list_networks
network id / ssid / bssid / flags
0    MySSID1 any [CURRENT]
1    MySSID2 any 

# The above result shows the two SSIDs configured in wpa_supplicant.conf
# Also shows MySSID1 is [CURRENT]ly connected  

> get_network 1 priority
0
> get_network 0 priority
0 

# This shows the *priority* of the two SSID/network ids (0 & 1)
# Also shows that initially, both are priority `0`  (equal priority)

> set_network 1 priority 2
OK 

# Assign a higher priority to network id 1 (MySSID2) 

> reassociate
OK  
... a series of CTRL_EVENTS are listed ... 

# reassociate causes the connection to switch to the highest priority 
# network id/SSID if available; that is now network id 1 (MySSID2) 

> list_networks
network id / ssid / bssid / flags
0    MySSID1     any
1    MySSID2     any [CURRENT] 

# confirmtion that network switch took place after `reassociate`  
# connection has moved to higher priority network/SSID [CURRENT] 

# to restore the original connection to MySSID1: 
# use the `set_network` priority commands above to prioritze MySSID1, 
# and follow that with another `reassociate`
# Note also: when priorities of all networks are equal, 
# wpa_supplicant defaults to the one with the strongest signal  

> quit
# terminates the wpa_cli interactive session  

$ 

And that's the switch wifi connections process. You should verify this works with your network configuration manually as I've shown above. Once verified, you may use the equivalent stand-alone commands to automate the process in a script - or experiment with wpa_cli running in daemon mode.

This procedure assumes your networks are properly configured. On RPi, part of properly configured means dhcpcd.conf is configured IAW best practices; e.g. do not use static ip unless you know what you are doing.


REFERENCES:

  1. RE: wlan0 vs. p2p-dev-wlan0
  2. ArchWiki wpa_supplicant documentation
  3. man wpa_cli on your RPi

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.