I'm trying to programmatically change which wifi network my PI is connected to, on the fly without a reboot. When I run the script using this USB wifi device it won't switch. However, it works when when using the built-in wifi card on the PI.

The external USB wifi is wlan0, and I'm forcing the onboard wifi to be wlan1 so they will always be consistent at boot-time (see this link)

cat > /etc/udev/rules.d/72-static-name.rules <<EOF
ACTION=="add", SUBSYSTEM=="net", DRIVERS=="brcmfmac", NAME="wlan2"

Here's the script. Note that for the onboard wifi, everything is the same except use wlan1 instead of wlan0:

#set primary network settings
wpa_cli -p /var/run/wpa_supplicant -i wlan0 add_network
wpa_cli -p /var/run/wpa_supplicant -i wlan0 set_network 0 ssid '"PrimaryAccessPoint"'
wpa_cli -p /var/run/wpa_supplicant -i wlan0 set_network 0 scan_ssid 1
wpa_cli -p /var/run/wpa_supplicant -i wlan0 set_network 0 key_mgmt WPA-PSK
wpa_cli -p /var/run/wpa_supplicant -i wlan0 set_network 0 psk '"password"'
wpa_cli -p /var/run/wpa_supplicant -i wlan0 enable_network 0

#set secondary network settings
wpa_cli -p /var/run/wpa_supplicant -iwlan0 add_network
wpa_cli -p /var/run/wpa_supplicant -iwlan0 set_network 1 ssid '"SecondaryAccessPoint"'
wpa_cli -p /var/run/wpa_supplicant -iwlan0 set_network 1 scan_ssid 1
wpa_cli -p /var/run/wpa_supplicant -iwlan0 set_network 1 key_mgmt WPA-PSK
wpa_cli -p /var/run/wpa_supplicant -iwlan0 set_network 1 psk '"password"'
wpa_cli -p /var/run/wpa_supplicant -iwlan0 enable_network 1

After running this script, network 1 (SecondaryAccessPoint) is the active network. When I want to to use network 0 (PrimaryAccessPoint) I run:

wpa_cli -p /var/run/wpa_supplicant -i wlan0 enable_network 0

When using wlan1, this works, and within 15 seconds when I run ifconfig I see the new ip address from PirmaryAccessPoint instead of from SecondaryAccessPoint.

However, for wlan0, it just does nothing. To debug, I did the following:

$ wpa_cli
Selected interface 'wlan0'

Interactive mode

> select_network 0
<3>CTRL-EVENT-SSID-REENABLED id=0 ssid="PrimaryAccessPoint"
<3>Trying to associate with 80:37:73:cb:b0:fa (SSID='PrimaryAccessPoint' freq=2437 MHz)
<3>Association request to the driver failed

I've tried running sudo systemctl restart dhcpcd according to this post but that didn't solve anything either. The only way I can get this to work is to reboot, and run the script for the access point I want first.

What does Association request to the driver failed mean, and how can I fix it? Why does it work on first connect, but fails afterwords? Is there a way around this?

Just for clarity's sake, I'll explain a little bit more of my objective here. Here is a link to my blog where I outline what I'm trying to do. In a nutshell, I'm using the onboard wifi to create an access point, and I'm using TWO external wifi cards. One external card (call it external1) will constantly be testing which open wifi access points are strongest (and fastest using speed test), and the other external card (call it external2) will connect to the "best" open network that external1 found and share that internet connection with the onboard card. Whenever external1 finds a better connection, it will reconfigure external2 to use that better connection.

Device version: RaspberryPI 3B+
OS: 2018-06-27-raspbian-stretch-lite
Kernel version: 4.14.69-v7+ #1141 SMP armv7l GNU/Linux

  • Rasbpian DOES NOT use Debian networking (by default) so wpa_cli will be inneffective. NOTE avoid other suggestions which suggest totally different network managers, and stick with the default. Your question does not explain why you have 2 connections, and/or why you need to change. See How to set up networking/WiFi – Milliways Sep 15 '18 at 0:21
  • @Milliways I updated my post to explain why I need to change. That "How to set up networking/WiFi" post was one of the first I tried, but it does not explain how to reload the wpa_supplicant-"$interface".conf once I have changed it. I need to do this without rebooting. Any ideas? – TwitchBronBron Sep 15 '18 at 1:15
  • 2
    I ran into this as well ("Association request to the driver failed") when trying to change networks on the fly. This seems to be a shortcoming of the 8192cu driver in Stretch (apparently it works in Jessie). This question contains a work-around by removing and re-adding the driver when needed: raspberrypi.stackexchange.com/questions/88137/… – Mike Fischer Oct 24 '18 at 23:43

You have two wifi devices so it should not be any problem to run them together and independently. You should be able to switch them as you like. On Raspbian you can do it with systemd. I would configure two interfaces and setup wpa_supplicant.

Switch over to systemd-networkd

# enable journaling
rpi ~$ sudo -Es
rpi ~# mkdir -p /var/log/journal
rpi ~# systemd-tmpfiles --create --prefix /var/log/journal #ignore warnings (*)

# disable classic networking
rpi ~# systemctl mask networking.service
rpi ~# systemctl mask dhcpcd.service
rpi ~# sudo mv /etc/network/interfaces /etc/network/interfaces~
rpi ~# sed -i '1i resolvconf=NO' /etc/resolvconf.conf

# enable systemd-networkd
rpi ~# systemctl enable systemd-networkd.service
rpi ~# systemctl enable systemd-resolved.service
rpi ~# ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

(*) You will get one or two confusing warnings "...Cannot set file attribute..." This are not errors and doesn't matter in this case.

Configure wpa_supplicant

To configure wpa_supplicant create these files with your settings for country=. You can just copy and paste this in one block to your command line beginning with cat and including EOF (delimiter EOF will not get part of the file):

rpi ~# cat > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf <<EOF
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev


rpi ~# cat > /etc/wpa_supplicant/wpa_supplicant-wlan1.conf <<EOF
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev


rpi ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
rpi ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan1.conf
rpi ~# systemctl disable wpa_supplicant.service
rpi ~# systemctl enable wpa_supplicant@wlan0.service
rpi ~# systemctl enable wpa_supplicant@wlan1.service

Configure the wlan interfaces

Create these files with the MACAdresses from your interfaces:

rpi ~# cat > /etc/systemd/network/02-wlan0.link <<EOF

rpi ~# cat > /etc/systemd/network/04-wlan1.link <<EOF

rpi ~# cat > /etc/systemd/network/08-wlan0.network <<EOF

rpi ~# cat > /etc/systemd/network/12-wlan1.network <<EOF


Now you should be able to switch the connections as you like with:

sudo systemctl stop wpa_supplicant@wlan0.service
sudo systemctl start wpa_supplicant@wlan0.service
sudo systemctl stop wpa_supplicant@wlan1.service
sudo systemctl start wpa_supplicant@wlan1.service
| improve this answer | |
  • I updated my post to better explain what I'm trying to do. Unfortunately this doesn't quite accomplish what I need. I will be determining the access point names on the fly, and I might need to change from AP1 to AP2, then AP2 to AP3, etc. It could change quite frequently, and to more than just 2 of them. Also, I'll be using the onboard wifi to broadcast an access point of my own, so it's not even available to be used in this way. – TwitchBronBron Sep 15 '18 at 1:19
  • @TwitchBronBron Seems you like your idea and try to solve exactly this setup. You try to copy human doing to a computer with a bunch of hardware but we know that it has very great difficulties doing so. For example if you switch the network, running streams will break. Any client watching video have to reconnect. – Ingo Sep 15 '18 at 10:17
  • @TwitchBronBron Other solutions may be long antennas over campers, beam radio (talk with the camp owner), looking at wpa_supplicant config what it can do to select best connection (it can do much), using 4G support from a provider. I know you will find arguments why all this does not work. Good luck. – Ingo Sep 15 '18 at 10:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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