For some inexplicable reason, our digital picture frame in the living room occasionally loses its WiFi connection. Sometimes, it’s entirely stable for three months; sometimes, it stops working a few times during the week.
Whenever this happens, I have to hard reboot the picture frame by briefly unplugging it.
Turning the Wi-Fi power management off has helped, but this issue has surfaced again during the warm summer months.
Of course, it always happens when I am away, so my wife can’t turn the frame on or off via voice command any more.
This is not helpful.
So, I wrote a short script that checks every five minutes if the internet connection is still there. If not, it restarts the network manager and makes a log entry.
Sometimes, the solution can be so easy.
What the script does
In simple terms, the script does the following:
- It pings Google’s DNS server (8.8.8.8) to check if the Raspberry Pi has internet connectivity
- If that fails, it resets the WiFi connection, attempting to restore internet access.
- It appends a log entry with a time stamp like “Internet connection lost. Restarting Network Manager… Logged failure at 2024-09-12 19:33:04”
- The script then sleeps for 300 seconds (5 minutes) before rechecking the connection.
This simple monitoring script ensures that any WiFi disconnections are handled automatically and logged for review.
I also ensure that the script is always active. If it has stopped unexpectedly, it is restarted.
The Python script
Open up a terminal window, connect to your Raspberry Pi, and type
sudo nano /home/pi/check_wifi.py
Next, copy and paste this script into your file.
#!/usr/bin/python3
# coding: utf8 #
import subprocess
import time
from datetime import datetime
# Log file location
log_file_path = "/home/pi/wifi_failures.txt"
def check_internet_connection():
try:
# Ping Google's DNS server to check for internet connection
subprocess.check_call(['ping', '-c', '1', '8.8.8.8'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return True
except subprocess.CalledProcessError:
return False
def restart_network():
# Restart network manager
time.sleep(300)
subprocess.run(["sudo", "systemctl", "restart", "NetworkManager"])
def log_wifi_failure():
try:
with open(log_file_path, 'a') as log_file:
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_file.write(f"[{current_time}] Internet connection lost. Network Manager restarted.\n")
print(f"Logged failure at {current_time}")
except Exception as e:
print(f"Failed to log the incident: {e}")
def main():
while True:
if not check_internet_connection():
print("Internet connection lost. Restarting Network Manager...")
# Introduce a 5-minute pause after printing the message
restart_network()
log_wifi_failure()
else:
# Add a timestamp to the "Internet connection is active." message
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"[{current_time}] Internet connection is active.")
# Wait for 5 minutes before the next check
time.sleep(300)
if __name__ == "__main__":
main()
If your Pi has a different home directory than “pi”, you must change this in the log file location.
The various parts of the script explained
Here is a quick explainer of how this script works:
Imports and Setup
import subprocess
import time
from datetime import datetime
- subprocess: Used to run system commands (like ping and restarting the network manager).
- time: Used for creating time delays between network checks.
- datetime: Used to log the exact date and time of any WiFi failures.
Variables
log_file_path = "/home/pi/wifi_failures_log.txt"
log_file_path: The location of the file where WiFi failures are logged.
Checking Internet Connection
def check_internet_connection():
try:
subprocess.check_call(['ping', '-c', '1', '8.8.8.8'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return True
except subprocess.CalledProcessError:
return False
- This function pings Google’s DNS server (8.8.8.8) to check if the Raspberry Pi has internet connectivity.
- If the ping command succeeds, it returns
True
(indicating the connection is active). - If the ping fails, it raises a
CalledProcessError
, and the function returnsFalse
(indicating the internet is down).
Restarting the Network
def restart_network():
subprocess.run(["sudo", "systemctl", "restart", "NetworkManager"])
- This function restarts the network manager using the
systemctl restart NetworkManager
command. This command resets the WiFi connection in case of failure, attempting to restore internet access.
Logging WiFi Failures
def log_wifi_failure():
try:
with open(log_file_path, 'a') as log_file:
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_file.write(f"[{current_time}] Internet connection lost. Network Manager restarted.\n")
print(f"Logged failure at {current_time}")
except Exception as e:
print(f"Failed to log the incident: {e}")
- This function logs each WiFi failure by:
- Opening the log file (
fantenrahmen_wifi_failures.txt
) in append mode ('a'
). - Write the current timestamp and send a message indicating that the network manager has been restarted.
- If there’s an issue with writing to the file, it will print an error message.
Main Loop
def main():
while True:
if not check_internet_connection():
print("Internet connection lost. Restarting Network Manager...")
restart_network()
log_wifi_failure()
else:
print("Internet connection is active.")
# Wait for 5 minutes before the next check
time.sleep(300)
- Infinite loop (
while True
): The script continuously checks the internet connection.check_internet_connection: If the function returnsFalse
(no internet connection), it: - Prints a message indicating that the internet is down.
- Calls
restart_network
to restart the network manager. - Logs the failure using the
log_wifi_failure
function. - If the connection is active, it prints “Internet connection is active.”Wait for 5 minutes (
time.sleep(300)
): The script sleeps for 300 seconds (5 minutes) before rechecking the connection, ensuring the check runs periodically.
Starting and restarting the script with systemd
To start the script at boot and restart it in case of failure, create a custom systemd
service.
sudo nano /etc/systemd/system/check_wifi.service
Add the following content to the service file:
[Unit]
Description=WiFi Check Script
After=network.target
[Service]
ExecStart=/usr/bin/python3 /home/pi/check_wifi.py
Restart=always
RestartSec=300
[Install]
WantedBy=multi-user.target
Explanation of the key parameters:
ExecStart
: The command to run your Python script. Ensure that the path topython3
andcheck_wifi.py
is correct.Restart=always
: This ensures the script will automatically restart if it crashes or fails.RestartSec=300
: This adds a 300-second delay before restarting the script.
After saving the file, reload systemd
to apply the new service file and enable the service to start on boot:
sudo systemctl daemon-reload
sudo systemctl enable check_wifi.service
Start the service immediately
sudo systemctl start check_wifi.service
You can verify if the service is running correctly by checking its status:
sudo systemctl status check_wifi.service
This setup will ensure the check_wifi.py
script runs at boot and automatically restarts after 60 seconds if it crashes.
Conclusion
This little script fixed a very annoying situation for me.
Now, it just checks regularly, and if there is no connection, it resets the Wi-Fi network, restoring the connection.
Mission accomplished.
Was this article helpful?
Thank you for your support and motivation.
Related Articles
- Check the wifi signal strength of your Raspberry Pi digital picture frame before you hang it up on the wall
- Three ways to change your wifi password and SSID on a headless Raspberry Pi locally and remotely
- How to find the IP address of a new device in your network with Angry IP Scanner
- Stay Connected: Enhancing Raspberry Pi Wi-Fi Stability by Turning Off Power Management