updated to monitor the netowrk and reset wifi if is not working
This commit is contained in:
@@ -0,0 +1,235 @@
|
||||
"""
|
||||
Network Monitoring Module
|
||||
Checks server connectivity and manages WiFi restart on connection failure
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import time
|
||||
import random
|
||||
import requests
|
||||
from datetime import datetime
|
||||
from kivy.logger import Logger
|
||||
from kivy.clock import Clock
|
||||
|
||||
|
||||
class NetworkMonitor:
|
||||
"""Monitor network connectivity and manage WiFi restart"""
|
||||
|
||||
def __init__(self, server_url, check_interval_min=30, check_interval_max=45, wifi_restart_duration=20):
|
||||
"""
|
||||
Initialize network monitor
|
||||
|
||||
Args:
|
||||
server_url (str): Server URL to check connectivity (e.g., 'https://digi-signage.moto-adv.com')
|
||||
check_interval_min (int): Minimum minutes between checks (default: 30)
|
||||
check_interval_max (int): Maximum minutes between checks (default: 45)
|
||||
wifi_restart_duration (int): Minutes to keep WiFi off during restart (default: 20)
|
||||
"""
|
||||
self.server_url = server_url.rstrip('/')
|
||||
self.check_interval_min = check_interval_min * 60 # Convert to seconds
|
||||
self.check_interval_max = check_interval_max * 60 # Convert to seconds
|
||||
self.wifi_restart_duration = wifi_restart_duration * 60 # Convert to seconds
|
||||
self.is_monitoring = False
|
||||
self.scheduled_event = None
|
||||
self.consecutive_failures = 0
|
||||
self.max_failures_before_restart = 3 # Restart WiFi after 3 consecutive failures
|
||||
|
||||
def start_monitoring(self):
|
||||
"""Start the network monitoring loop"""
|
||||
if not self.is_monitoring:
|
||||
self.is_monitoring = True
|
||||
Logger.info("NetworkMonitor: Starting network monitoring")
|
||||
self._schedule_next_check()
|
||||
|
||||
def stop_monitoring(self):
|
||||
"""Stop the network monitoring"""
|
||||
self.is_monitoring = False
|
||||
if self.scheduled_event:
|
||||
self.scheduled_event.cancel()
|
||||
self.scheduled_event = None
|
||||
Logger.info("NetworkMonitor: Stopped network monitoring")
|
||||
|
||||
def _schedule_next_check(self):
|
||||
"""Schedule the next connectivity check at a random interval"""
|
||||
if not self.is_monitoring:
|
||||
return
|
||||
|
||||
# Random interval between min and max
|
||||
next_check_seconds = random.randint(self.check_interval_min, self.check_interval_max)
|
||||
next_check_minutes = next_check_seconds / 60
|
||||
|
||||
Logger.info(f"NetworkMonitor: Next check scheduled in {next_check_minutes:.1f} minutes")
|
||||
|
||||
# Schedule using Kivy Clock
|
||||
self.scheduled_event = Clock.schedule_once(
|
||||
lambda dt: self._check_connectivity(),
|
||||
next_check_seconds
|
||||
)
|
||||
|
||||
def _check_connectivity(self):
|
||||
"""Check network connectivity to server"""
|
||||
Logger.info("NetworkMonitor: Checking server connectivity...")
|
||||
|
||||
if self._test_server_connection():
|
||||
Logger.info("NetworkMonitor: ✓ Server connection successful")
|
||||
self.consecutive_failures = 0
|
||||
else:
|
||||
self.consecutive_failures += 1
|
||||
Logger.warning(f"NetworkMonitor: ✗ Server connection failed (attempt {self.consecutive_failures}/{self.max_failures_before_restart})")
|
||||
|
||||
if self.consecutive_failures >= self.max_failures_before_restart:
|
||||
Logger.error("NetworkMonitor: Multiple connection failures detected - initiating WiFi restart")
|
||||
self._restart_wifi()
|
||||
self.consecutive_failures = 0 # Reset counter after restart
|
||||
|
||||
# Schedule next check
|
||||
self._schedule_next_check()
|
||||
|
||||
def _test_server_connection(self):
|
||||
"""
|
||||
Test connection to the server using ping only
|
||||
This works in closed networks where the server is local
|
||||
|
||||
Returns:
|
||||
bool: True if server is reachable, False otherwise
|
||||
"""
|
||||
try:
|
||||
# Extract hostname from server URL (remove http:// or https://)
|
||||
hostname = self.server_url.replace('https://', '').replace('http://', '').split('/')[0]
|
||||
|
||||
Logger.info(f"NetworkMonitor: Pinging server: {hostname}")
|
||||
|
||||
# Ping the server hostname with 3 attempts
|
||||
result = subprocess.run(
|
||||
['ping', '-c', '3', '-W', '3', hostname],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
Logger.info(f"NetworkMonitor: ✓ Server {hostname} is reachable")
|
||||
return True
|
||||
else:
|
||||
Logger.warning(f"NetworkMonitor: ✗ Cannot reach server {hostname}")
|
||||
return False
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
Logger.warning(f"NetworkMonitor: ✗ Ping timeout to server")
|
||||
return False
|
||||
except Exception as e:
|
||||
Logger.error(f"NetworkMonitor: Error pinging server: {e}")
|
||||
return False
|
||||
|
||||
def _restart_wifi(self):
|
||||
"""
|
||||
Restart WiFi by turning it off for a specified duration then back on
|
||||
This runs in a separate thread to not block the main application
|
||||
"""
|
||||
def wifi_restart_thread():
|
||||
try:
|
||||
Logger.info("NetworkMonitor: ====================================")
|
||||
Logger.info("NetworkMonitor: INITIATING WIFI RESTART SEQUENCE")
|
||||
Logger.info("NetworkMonitor: ====================================")
|
||||
|
||||
# Turn off WiFi using rfkill (more reliable on Raspberry Pi)
|
||||
Logger.info("NetworkMonitor: Turning WiFi OFF using rfkill...")
|
||||
result = subprocess.run(
|
||||
['sudo', 'rfkill', 'block', 'wifi'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
Logger.info("NetworkMonitor: ✓ WiFi turned OFF successfully (rfkill)")
|
||||
Logger.info("NetworkMonitor: WiFi is now DISABLED and will remain OFF")
|
||||
else:
|
||||
Logger.error(f"NetworkMonitor: rfkill failed, trying ifconfig...")
|
||||
Logger.error(f"NetworkMonitor: rfkill error: {result.stderr}")
|
||||
|
||||
# Fallback to ifconfig
|
||||
result2 = subprocess.run(
|
||||
['sudo', 'ifconfig', 'wlan0', 'down'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
if result2.returncode == 0:
|
||||
Logger.info("NetworkMonitor: ✓ WiFi turned OFF successfully (ifconfig)")
|
||||
else:
|
||||
Logger.error(f"NetworkMonitor: Failed to turn WiFi off: {result2.stderr}")
|
||||
Logger.error(f"NetworkMonitor: Return code: {result2.returncode}")
|
||||
Logger.error(f"NetworkMonitor: STDOUT: {result2.stdout}")
|
||||
return
|
||||
|
||||
# Wait for the specified duration with WiFi OFF
|
||||
wait_minutes = self.wifi_restart_duration / 60
|
||||
Logger.info(f"NetworkMonitor: ====================================")
|
||||
Logger.info(f"NetworkMonitor: WiFi will remain OFF for {wait_minutes:.0f} minutes")
|
||||
Logger.info(f"NetworkMonitor: Waiting period started at: {datetime.now().strftime('%H:%M:%S')}")
|
||||
Logger.info(f"NetworkMonitor: ====================================")
|
||||
|
||||
# Sleep while WiFi is OFF
|
||||
time.sleep(self.wifi_restart_duration)
|
||||
|
||||
Logger.info(f"NetworkMonitor: Wait period completed at: {datetime.now().strftime('%H:%M:%S')}")
|
||||
|
||||
# Turn WiFi back on after the wait period
|
||||
Logger.info("NetworkMonitor: ====================================")
|
||||
Logger.info("NetworkMonitor: Now turning WiFi back ON...")
|
||||
Logger.info("NetworkMonitor: ====================================")
|
||||
|
||||
# Unblock WiFi using rfkill
|
||||
result = subprocess.run(
|
||||
['sudo', 'rfkill', 'unblock', 'wifi'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
Logger.info("NetworkMonitor: ✓ WiFi unblocked successfully (rfkill)")
|
||||
else:
|
||||
Logger.error(f"NetworkMonitor: rfkill unblock failed: {result.stderr}")
|
||||
|
||||
# Also bring interface up
|
||||
result2 = subprocess.run(
|
||||
['sudo', 'ifconfig', 'wlan0', 'up'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
if result2.returncode == 0:
|
||||
Logger.info("NetworkMonitor: ✓ WiFi interface brought UP successfully")
|
||||
|
||||
# Wait a bit for connection to establish
|
||||
Logger.info("NetworkMonitor: Waiting 10 seconds for WiFi to initialize...")
|
||||
time.sleep(10)
|
||||
|
||||
# Try to restart DHCP
|
||||
Logger.info("NetworkMonitor: Requesting IP address...")
|
||||
subprocess.run(
|
||||
['sudo', 'dhclient', 'wlan0'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=15
|
||||
)
|
||||
|
||||
Logger.info("NetworkMonitor: ====================================")
|
||||
Logger.info("NetworkMonitor: WIFI RESTART SEQUENCE COMPLETED")
|
||||
Logger.info("NetworkMonitor: ====================================")
|
||||
else:
|
||||
Logger.error(f"NetworkMonitor: Failed to turn WiFi on: {result.stderr}")
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
Logger.error("NetworkMonitor: WiFi restart command timeout")
|
||||
except Exception as e:
|
||||
Logger.error(f"NetworkMonitor: Error during WiFi restart: {e}")
|
||||
|
||||
# Run in separate thread to not block the application
|
||||
import threading
|
||||
thread = threading.Thread(target=wifi_restart_thread, daemon=True)
|
||||
thread.start()
|
||||
Reference in New Issue
Block a user