How to fix an unreliable WiFi connection on your Raspberry Pi picture frame

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:

  1. It pings Google’s DNS server (8.8.8.8) to check if the Raspberry Pi has internet connectivity
  2. If that fails, it resets the WiFi connection, attempting to restore internet access.
  3. 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”
  4. 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 returns False (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 returns False (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 to python3 and check_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.


Scroll to Top