Raspberry Pi – Auto WiFi Hotspot Switch – Direct Connection
Raspberry Pi – Auto WiFi Hotspot Switch – Direct Connection

Raspberry Pi – Auto WiFi Hotspot Switch – Direct Connection

Note: This is not my work, it is copied from https://www.raspberryconnect.com/projects/65-raspberrypi-hotspot-accesspoints/158-raspberry-pi-auto-wifi-hotspot-switch-direct-connection. I have made a copy incase the orginal gets lost. Please check the orginal for updates and not mine.

A script to allow the Raspberry Pi to connect to a know wifi router or automatically generate a Non Internet Hotspot Access Point if no network is found. You can then use SSH or VNC on the move and switch between the hotspot and home network without a reboot.

This is suitable for the Pi Zero W which has no Network port or anybody who does not need an internet routed access point on a Raspberry Pi 3 or 4. Just for direct Wifi access to the PI when you are out and about.

Works with Raspbian Buster, Stretch and Jessie.

When i am home I like to have my Raspberry Pi connected to the home network and the internet but when I am out I would like to connect to it using ssh via a hotspot using a tablet, phone or laptop.

I wanted a Raspberry Pi that connects to my home networks Wifi when I am at home or generates a wifi Hotspot/Access Point when I am out.

I have done this in a previous script but, this is an updated process and more robust than my original script. So this article is how to setup a Raspberry Pi so it can automatically switch between a network wifi connection and a non internet hotspot.

If you do require an internet routed hotspot as you have a RPi4, RPi3 B+, RPi3 or a RPi 1/2 with a wifi dongle then use my alternative script at Raspberry Pi – Auto WiFI Hotspot Switch Internet

If you would just like a permanent hotspot then you can use this guide Raspberry Pi – Hotspot/Access Point dhcpcd method

Easy Installer Script: the setup in this guide is available in an installer at Raspberry Pi AutoHotspot and Static Hotspot Installer Script

Aim:

  • When your home:   On starting the Raspberry Pi it connects to your home routers wifi
  • When your out: On starting, if any known wifi connection is not found it will generate a hotspot so a direct wifi connection can be made to the Raspberry Pi by a tablet, phone or laptop.  Useful for SSH, VNC and webservers.
  • While in Hotspot mode for RPi 1/2/3/4:  if an ethernet cable is connected the Raspberry Pi, then it will NOT have internet access

Additional Features:

Using a Cron, a timer can be setup so the wifi connection can be regulary checked. It will switch between a wifi router and a hotspot without a reboot depending on the results. This is useful for

  • Raspberry Pi in car entertainment systems
  • Raspberry Pi Dash Cams
  • If the RPi looses wifi connection in your garden or near your home when using the camera or sensors.
  • You run a script or program at home connected to your router and wish to monitor it while you are out. As a hotspot is generated without a reboot the script/program is not interuppted.

It is also possible to run the script from a GPIO button so you can manually run the script to switch depending on where you are.

 Requirements:

This has been tested on Raspbian Buster, Stretch, Jessie. To see which version you have enter the command lsb_release -a

  • Raspberry Pi Zero W or Raspberry Pi 3, RPi3B+, RPi4
  • Raspberry Pi 1,2 or Zero with a Wifi Dongle*,
  • Wifi already configured for your home router

*some WiFi dongles don’t work in adhoc/AP mode or don’t work with with the nl80211 driver used with the RPi 3 & Pi zero W inbuilt wifi, so you may want to check this first before starting.

 This setup has been tested on Raspbian Jessie, Raspbian Stretch and Raspbian Buster using a RPi4, RPI3 B+, RPI3, RPI Zero W and a RPI 2 . A connection has been made to the Hotspot using an Android Tablet, Ipad2, Raspberry PI and Windows 10. All worked fine with SSH.

Note:

Dnsmasq bug: in versions below 2.77 on Stretch and Jessie, there is a bug that may cause the hotspot not to start for some users. This can be resolved by removing the dns-root-data. It may be benificial to do this before you start the rest of the installation as it has been reported that doing it after installation for effected users does not work but you won’t know if it is an issue until after the installation is complete.

check your version with : dpkg -s dnsmasq

versions 2.77 and above are ok. If not then try the command:

sudo apt-get purge dns-root-data

thanks to danny for highlighting this.

Note about Raspbian Stretch & Buster Network Device Names

For Raspbian Stretch there has been changes to how the network drivers are named, called Predictable Network Interface Names,  and may be different for the usual wlan0 and wlan1 for wifi and eth0 for ethernet connections. Though the official Foundation version of Raspbian seems to be keeping to the old standard names, at least at the time of writing,  this may not always be the case. For this guide I will use wlan0 as the device that is used.  

To check the device name for your setup enter the commmand iw dev and take a note of the “Interface” name. For wifi it should start with wl , replace your device name with any reference to wlan0 in the article, scripts and config files.

Step 1:

To start with hostapd hotspot client and dnsmasq lightweight dns server need to be installed.

Open a Terminal session.

Update Raspbian with the latest updates by entering the commands:

sudo apt-get update
sudo apt-get upgrade

 To install hostapd enter the command:

sudo apt-get install hostapd

enter Y when prompted.

To install dnsmasq enter the command:

sudo apt-get install dnsmasq

enter Y when prompted

The installers will have set up the programme so they run when the pi is started. For this setup they only need to be started if the home router is not found. So automatic startup needs to be disabled and by default hostapd is masked so needs to be unmasked. This is done with the following commands:

sudo systemctl unmask hostapd

sudo systemctl disable hostapd
sudo systemctl disable dnsmasq

Now the hostspot configuration file can be setup. This contains the name of the WiFi signal you will need to connect to (SSID) and the security password.

To edit the configuration files I will be using the nano text editor but if you prefer an editor with an point and click interface then replace nano with leafpad in the following instructions.

Hostapd Configuration

Using a text editor edit the hostapd configuration file. This file won’t exist at this stage so will be blank.

sudo nano /etc/hostapd/hostapd.conf

download file here:



#2.4GHz setup wifi 80211 b,g,n
interface=wlan0
driver=nl80211
ssid=RPiHotspot
hw_mode=g
channel=8
wmm_enabled=0
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=1234567890
wpa_key_mgmt=WPA-PSK
wpa_pairwise=CCMP TKIP
rsn_pairwise=CCMP

#80211n - Change GB to your WiFi country code
country_code=GB
ieee80211n=1
ieee80211d=1

  • The interface will be wlan0
  • The driver nl80211 works with the Raspberry Pi 3 & Zero W onboard WiFi but you will need to check that your wifi dongle is compatable and can use Access Point mode.

For more information on wifi dongles see elinux.org/RPi_USB_Wi-Fi_Adapters

  • The SSID is the name of the WiFi signal broadcast from the RPi, which you will connect to with your Tablet or phones WiFi settings.
  • Channel can be set between 1 and 13. If you are having trouble connection because of to many wifi signals in your area are using channel 6 then try another channel.
  • Wpa_passphrase is the password you will need to enter when you first connect a device to your Raspberry Pi’s hotspot. This should be at least 8 characters and a bit more difficult to guess than my example.
  • The country_code should be set to your country to comply with local RF laws. You may experience connection issues if this is not correct. Your country_code can be found in /etc/wpa_supplicant/wpa_supplicant.conf or in Raspberry Pi Configuration – Localisation settings

To save the config file press ctrl & o and to exit nano press Ctrl & x

Now the defaults file needs to be updated to point to where the config file is stored.
In terminal enter the command
sudo nano /etc/default/hostapd

Change:
#DAEMON_CONF=””
to
DAEMON_CONF=”/etc/hostapd/hostapd.conf”

Check the DAEMON_OPTS=”” is preceded by a #, so is #DAEMON_OPTS=””

And save.

DNSmasq configuration

Next dnsmasq needs to be configured to allow the Rpi to act as a router and issue ip addresses. Open the dnsmasq.conf file with

sudo nano /etc/dnsmasq.conf

Go to the bottom of the file and add the following lines (download here)


#AutoHotspot Config
#stop DNSmasq from using resolv.conf
no-resolv
#Interface to use
interface=wlan0
bind-interfaces
dhcp-range=10.0.0.50,10.0.0.150,12h

and the save (ctl & o) and exit (ctrl & x)

Step 2:

Now that hostapd and dnsmasq are configured we now need to make some changes to the interfaces file, add a service file and then add the autohotspot script.

The interfaces file is not required and should be empty of any network config. Depending which version of Raspbian you have this file may still contain network config.

Enter

sudo nano /etc/network/interfaces

If you file shows more than the standard top 5 lines like this

 # interfaces(5) file used by ifup(8) and ifdown(8) 
# Please note that this file is written to be used with dhcpcd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'
# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d

then make a copy of of your file and then remove any excess lines from the interfaces file.

To make a backup of your interfaces file use the command

sudo cp /etc/network/interfaces /etc/network/interfaces-backup

 DHCPCD

dhcpcd is the software that manages the network setup. The next step is to stop dhcpcd from starting the wifi network so the autohotspot script in the next step takes control of that. Ethernet will still be managed by dhcpcd.

Open dhcpcd.conf with the command

sudo nano /etc/dhcpcd.conf

at the bottom of the file enter the line

nohook wpa_supplicant

now save (ctrl & o) and exit (ctrl & x)

autohotspot service file

Next we have to create a service which will run the autohotspot script when the Raspberry Pi starts up.

create a new file with the command

sudo nano /etc/systemd/system/autohotspot.service

Then enter the following text or download here


[Unit]
Description=Automatically generates an internet Hotspot when a valid ssid is not in range
After=multi-user.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/autohotspot
[Install]
WantedBy=multi-user.target

and save (ctrl & o) and exit (ctrl & x)

For the service to work it has to be enabled. To do this enter the command

sudo systemctl enable autohotspot.service

AutoHotspot Script

This is the main script that will manage your wifi connections between a wifi router and an Hotspot.

It will search for any wifi connection that is setup on you Raspberry Pi by using the details found in /etc/wpa_supplicant/wpa_supplicant.conf

If no wifi signal is found for a known SSID then the script will shutdown the wifi network setup and create a Hotspot. Allowing you to connect to the Raspberry Pi from a wifi device using SSH or VNC.

 The script works with SSID’s that contain spaces and by entering your routers MAC address it can be used with hidden SSID’s.

Hidden SSIDs

If your routers SSID is not broadcast/hidden then find this section in the script

#Enter the Routers Mac Addresses for hidden SSIDs, seperated by spaces ie
#( ’11:22:33:44:55:66′ ‘aa:bb:cc:dd:ee:ff’ )
mac=()

and enter your routers MAC address in the brackets of mac=() as shown in the example. Make sure mutiple MAC addresses are seperated by a space.

 Creating the autohotspot script:

Create a new file with the command

sudo nano /usr/bin/autohotspot

and add the autohotspot script. This can be downloaded from here


#!/bin/bash
#version 0.95-41-N/HS

#You may share this script on the condition a reference to RaspberryConnect.com 
#must be included in copies or derivatives of this script. 

#A script to switch between a wifi network and a non internet routed Hotspot
#Works at startup or with a seperate timer or manually without a reboot
#Other setup required find out more at
#http://www.raspberryconnect.com

wifidev="wlan0" #device name to use. Default is wlan0.
#use the command: iw dev ,to see wifi interface name 

IFSdef=$IFS
cnt=0
#These four lines capture the wifi networks the RPi is setup to use
wpassid=$(awk '/ssid="/{ print $0 }' /etc/wpa_supplicant/wpa_supplicant.conf | awk -F'ssid=' '{ print $2 }' ORS=',' | sed 's/\"/''/g' | sed 's/,$//')
wpassid=$(echo "${wpassid//[$'\r\n']}")
IFS="," ssids=($wpassid) IFS=$IFSdef #reset back to defaults #Note:If you only want to check for certain SSIDs #Remove the # in in front of ssids=('mySSID1'.... below and put a # infront of all four lines above # separated by a space, eg ('mySSID1' 'mySSID2') #ssids=('mySSID1' 'mySSID2' 'mySSID3') #Enter the Routers Mac Addresses for hidden SSIDs, seperated by spaces ie #( '11:22:33:44:55:66' 'aa:bb:cc:dd:ee:ff' ) mac=() ssidsmac=("${ssids[@]}" "${mac[@]}") #combines ssid and MAC for checking createAdHocNetwork() { echo "Creating Hotspot" ip link set dev "$wifidev" down ip a add 10.0.0.5/24 brd + dev "$wifidev" ip link set dev "$wifidev" up dhcpcd -k "$wifidev" >/dev/null 2>&1 systemctl start dnsmasq systemctl start hostapd } KillHotspot() { echo "Shutting Down Hotspot" ip link set dev "$wifidev" down systemctl stop hostapd systemctl stop dnsmasq ip addr flush dev "$wifidev" ip link set dev "$wifidev" up dhcpcd -n "$wifidev" >/dev/null 2>&1 } ChkWifiUp() { echo "Checking WiFi connection ok" sleep 20 #give time for connection to be completed to router if ! wpa_cli -i "$wifidev" status | grep 'ip_address' >/dev/null 2>&1 then #Failed to connect to wifi (check your wifi settings, password etc) echo 'Wifi failed to connect, falling back to Hotspot.' wpa_cli terminate "$wifidev" >/dev/null 2>&1 createAdHocNetwork fi } FindSSID() { #Check to see what SSID's and MAC addresses are in range ssidChk=('NoSSid') i=0; j=0 until [ $i -eq 1 ] #wait for wifi if busy, usb wifi is slower. do ssidreply=$((iw dev "$wifidev" scan ap-force | egrep "^BSS|SSID:") 2>&1) >/dev/null 2>&1 echo "SSid's in range: " $ssidreply echo "Device Available Check try " $j if (($j >= 10)); then #if busy 10 times goto hotspot echo "Device busy or unavailable 10 times, going to Hotspot" ssidreply="" i=1 elif echo "$ssidreply" | grep "No such device (-19)" >/dev/null 2>&1; then echo "No Device Reported, try " $j NoDevice elif echo "$ssidreply" | grep "Network is down (-100)" >/dev/null 2>&1 ; then echo "Network Not available, trying again" $j j=$((j + 1)) sleep 2 elif echo "$ssidreply" | grep "Read-only file system (-30)" >/dev/null 2>&1 ; then echo "Temporary Read only file system, trying again" j=$((j + 1)) sleep 2 elif echo "$ssidreply" | grep "Invalid exchange (-52)" >/dev/null 2>&1 ; then echo "Temporary unavailable, trying again" j=$((j + 1)) sleep 2 elif ! echo "$ssidreply" | grep "resource busy (-16)" >/dev/null 2>&1 ; then echo "Device Available, checking SSid Results" i=1 else #see if device not busy in 2 seconds echo "Device unavailable checking again, try " $j j=$((j + 1)) sleep 2 fi done for ssid in "${ssidsmac[@]}" do if (echo "$ssidreply" | grep "$ssid") >/dev/null 2>&1 then #Valid SSid found, passing to script echo "Valid SSID Detected, assesing Wifi status" ssidChk=$ssid return 0 else #No Network found, NoSSid issued" echo "No SSid found, assessing WiFi status" ssidChk='NoSSid' fi done } NoDevice() { #if no wifi device,ie usb wifi removed, activate wifi so when it is #reconnected wifi to a router will be available echo "No wifi device connected" wpa_supplicant -B -i "$wifidev" -c /etc/wpa_supplicant/wpa_supplicant.conf >/dev/null 2>&1 exit 1 } FindSSID #Create Hotspot or connect to valid wifi networks if [ "$ssidChk" != "NoSSid" ] then if systemctl status hostapd | grep "(running)" >/dev/null 2>&1 then #hotspot running and ssid in range KillHotspot echo "Hotspot Deactivated, Bringing Wifi Up" wpa_supplicant -B -i "$wifidev" -c /etc/wpa_supplicant/wpa_supplicant.conf >/dev/null 2>&1 ChkWifiUp elif { wpa_cli -i "$wifidev" status | grep 'ip_address'; } >/dev/null 2>&1 then #Already connected echo "Wifi already connected to a network" else #ssid exists and no hotspot running connect to wifi network echo "Connecting to the WiFi Network" wpa_supplicant -B -i "$wifidev" -c /etc/wpa_supplicant/wpa_supplicant.conf >/dev/null 2>&1 ChkWifiUp fi else #ssid or MAC address not in range if systemctl status hostapd | grep "(running)" >/dev/null 2>&1 then echo "Hostspot already active" elif { wpa_cli status | grep "$wifidev"; } >/dev/null 2>&1 then echo "Cleaning wifi files and Activating Hotspot" wpa_cli terminate >/dev/null 2>&1 ip addr flush "$wifidev" ip link set dev "$wifidev" down rm -r /var/run/wpa_supplicant >/dev/null 2>&1 createAdHocNetwork else #"No SSID, activating Hotspot" createAdHocNetwork fi fi

and save (ctl & o) and exit (ctl & x)

For the autohotspot script to work it needs to be executable. This is done with the command

sudo chmod +x /usr/bin/autohotspot

Thats it, you are ready to go. Now test that everything is working ok.

Thanks to Willem Me and Tino for there contributions to the development of this script.

Testing the Hotspot

To test that the RPi is setup ok reboot the RPI. When the desktop returns you should have the wifi icon Raspbian Pixel WiFI icon by the clock.
For those setting this up on a headerless RPi then you should see the pi on your routers network. 

To test the hotspot works ok edit the ssid name of your router in the wpa_supplicant file.

enter

sudo nano /etc/wpa_supplicant/wpa_supplicant.conf

and add ‘off’ to the end of your routers ssid. For example:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=GB
network={ ssid="mySSID1" psk="myPassword" key_mgmt=WPA-PSK }

change to

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=GB
network={ ssid="mySSID1off" psk="myPassword" key_mgmt=WPA-PSK }

save (ctrl & o) and close (ctrl & x) the file

Now reboot the Raspberry Pi.

Once the RPi is up and running the wifi icon near the clock should now be two red crosses Raspbian Pixel AP mode icon This means it is an access point, it could also mean your network is down but other devices should detect the hotspot. On a Tablet, phone or Laptop scan for wifi signals. You should see one for RPiHotSpot.

Select this as the wifi signal to connect to. The password is what you setup in the hostapd.conf file. From my example it is 1234567890

Wifi Connections-android

If you find this guide useful and wish to show your appreciation then you are welcome to make a donation or share a link to this article. There is no obligation to do so, this guide is free for use and support is available to everybody as long as I know the answer 🙂 RaspberryConnect.com  

Local wifi signals in range on Android. Will be RPiHotSpot not RPI3Hot

For SSH and VNC the connection ip is 10.0.0.5 also if you have setup the Rpi as a webserver use the same ip to see the webpage.

For ssh use ssh [email protected]

For vnc use 10.0.0.5::5900

 Once you are happy the setup is working ok change the wpa_supplicant.conf file back to your routers ssid. From the next reboot the autohotspot script will manage your wifi connection.

Setting up a Timer

If the autohotspot script is set to be run at set intervals, when you go out of range of your home router it will automatically generate a hotspot and then when you get back in range it will deactivate the hotspot and connect to the routers wifi. If you run a program in the background or use programs like tmux then any software you are running will keep working.

If you have an active ssh or vnc session running when the switch happens it will be lost.

Using a Cron job, tasks can be set off automatically at certain times, dates or intervals. For my use running the script every 5 minutes is fine but this can be changed to your needs. To setup a cron task enter the command

crontab -e

At the bottom of the file enter the command

*/5 * * * * sudo /usr/bin/autohotspot >/dev/null 2>&1

There is a space after each entry and * except the first *.

The first * position is for minutes. If you want it to check every minute just use * instead of */5

If you want to use hours, say every 2 hours enter it as

* */2 * * * sudo /usr/bin/autohotspot >/dev/null 2>&1

 Save the cron tab with ctrl & o and close it with ctrl & x

The cron job will automatically start straight away.

Disable Cron Timer

If you no longer need the timer running edit the cron with

crontab -e

and put a # infront so it is now

#*/5 * * * * sudo /usr/bin/autohotspot

The script will now only work at boot up or if you manually run the autohotspot script with the command

sudo /usr/bin/autohotspot

Note on Permissions:

by default the pi user does not need to enter a password to use the sudo command. If you are not using the default pi user and while doing this guide you have had to enter a password every time sudo is needed then you will find the the cron job will not work as it wont have permission to run the autohotspot script.

To fix this you can give the user permission to run the script without a password.
Enter the command

sudo visudo

enter your password
at the bottom of the file add the following line, where username is the user that will be using the script:

username ALL= NOPASSWD: /usr/bin/autohotspot

Now you will be able to run the script with sudo with the cron.

Thanks to Jim for pointing this out as an issue for some users.

If you are not using the default PI user and you are still have issues then check your default Paths from CRON for your user. It will need /sbin/ for iw.

Adding the path line to the cron will tell it were to look, PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Thanks to Atanas Atanasov for highligting this for non PI users

Script Removal

If you don’t wish to continue using the autohotspot script then the Raspberry Pi can be revered back to a standard wifi setup with the following steps.

Disable the script with the command

sudo systemctl disable autohotspot

In the /etc/dhcpcd.conf file remove the line that was added

nohook wpa_supplicant

If you had previous config in your interfaces file and made a backup you can restore your original interfaces file with the command

sudo mv /etc/network/interfaces-backup /etc/network/interfaces

Then reboot.

The autohotspot script will no longer have control of your wifi. Dnsmasq and hostapd can be uninstalled if you no longer need them.

 Trouble Shooting

  • If you get no wifi connection or no hotspot  then it is most likely the autohotspot script is not executable or the service has not been enabled

redo the follow commands

sudo chmod +x /usr/bin/autohotspot

sudo systemctl enable autohotspot.service

  • You are in range of your router but it only creates a hotspot. If there is an issue with connecting to the router, such as the password is wrong. The script will fall back to the hotspot so you still have some type of connection. Check your password in the wpa_supplicant.conf file. 
  • You can connect to the hotspot via an Android Phone but you can’t get a ssh connection. Some users have found this issue where Android uses there data connection rather than the wifi. Disabeling data has allowed them to use ssh.   
  • If this setup is not working as expected you can check the script for errors by running it manually in a terminal window with the command, sudo /usr/bin/autohotspot ,you can also check the service status with, sudo systemctl status -l autohotspot ,and if the hotspot has failed try, sudo systemctl status -l hostapd
  • You need to add a new wifi network to the RPi but it is in Hotspot mode so you are unable to scan for new wifi signals. You will need to add the new network to /etc/wpa_supplicant/wpa_supplicant manually. Enter the following details replacing mySSID and myPassword with the correct details. If your router has a hidden SSID/not Broadcast then include the line;  scan_ssid=1
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=GB

network={ ssid="mySSID1" psk="myPassword" key_mgmt=WPA-PSK }
  • Unable to Authenticate the RPIHotSpot connection from another device. Make sure the password for the wifi connection is the one in the hosapd.conf file and not your Raspberry Pi’s user password. The default pasword is 1234567890

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.