271 lines
9.0 KiB
Python
271 lines
9.0 KiB
Python
"""
|
|
WiFi recovery module for handling server disconnection
|
|
Monitors server connectivity and auto-restarts WiFi if connection is lost
|
|
"""
|
|
|
|
import subprocess
|
|
import time
|
|
import threading
|
|
import logging
|
|
from datetime import datetime
|
|
from logger_module import log_with_server
|
|
|
|
|
|
class WiFiRecoveryManager:
|
|
"""
|
|
Manages WiFi recovery when server connection is lost
|
|
Restarts WiFi after 20 minutes of consecutive connection failures
|
|
"""
|
|
|
|
def __init__(self, hostname, device_ip, check_interval=60, failure_threshold=5):
|
|
"""
|
|
Initialize WiFi recovery manager
|
|
|
|
Args:
|
|
hostname: Device hostname
|
|
device_ip: Device IP
|
|
check_interval: Seconds between connectivity checks
|
|
failure_threshold: Number of consecutive failures before WiFi restart
|
|
"""
|
|
self.hostname = hostname
|
|
self.device_ip = device_ip
|
|
self.check_interval = check_interval
|
|
self.failure_threshold = failure_threshold
|
|
self.consecutive_failures = 0
|
|
self.is_wifi_down = False
|
|
self.monitor_thread = None
|
|
self.is_running = False
|
|
self.wifi_down_time = 1200 # 20 minutes in seconds
|
|
|
|
logging.basicConfig(level=logging.INFO)
|
|
self.logger = logging.getLogger(__name__)
|
|
|
|
|
|
def get_wifi_interface(self):
|
|
"""Detect WiFi interface (wlan0 or wlan1)"""
|
|
try:
|
|
result = subprocess.run(
|
|
['ip', 'link', 'show'],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=10
|
|
)
|
|
|
|
if 'wlan0' in result.stdout:
|
|
return 'wlan0'
|
|
elif 'wlan1' in result.stdout:
|
|
return 'wlan1'
|
|
else:
|
|
self.logger.error("No WiFi interface found")
|
|
return None
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error detecting WiFi interface: {e}")
|
|
return None
|
|
|
|
|
|
def stop_wifi(self, interface):
|
|
"""Stop WiFi interface"""
|
|
try:
|
|
self.logger.info(f"Stopping WiFi interface: {interface}")
|
|
log_with_server(f"Stopping WiFi interface {interface}", self.hostname, self.device_ip)
|
|
|
|
subprocess.run(
|
|
['sudo', 'ip', 'link', 'set', interface, 'down'],
|
|
check=True,
|
|
timeout=10
|
|
)
|
|
self.is_wifi_down = True
|
|
return True
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Failed to stop WiFi: {e}")
|
|
log_with_server(f"ERROR: Failed to stop WiFi: {str(e)}", self.hostname, self.device_ip)
|
|
return False
|
|
|
|
|
|
def start_wifi(self, interface):
|
|
"""Start WiFi interface"""
|
|
try:
|
|
self.logger.info(f"Starting WiFi interface: {interface}")
|
|
log_with_server(f"Starting WiFi interface {interface}", self.hostname, self.device_ip)
|
|
|
|
subprocess.run(
|
|
['sudo', 'ip', 'link', 'set', interface, 'up'],
|
|
check=True,
|
|
timeout=10
|
|
)
|
|
self.is_wifi_down = False
|
|
return True
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Failed to start WiFi: {e}")
|
|
log_with_server(f"ERROR: Failed to start WiFi: {str(e)}", self.hostname, self.device_ip)
|
|
return False
|
|
|
|
|
|
def reconnect_wifi(self, interface, wifi_down_time=1200):
|
|
"""
|
|
Perform WiFi disconnect and reconnect cycle
|
|
|
|
Args:
|
|
interface: WiFi interface to reset
|
|
wifi_down_time: Time to keep WiFi disabled (seconds)
|
|
"""
|
|
self.logger.info(f"WiFi recovery: Stopping for {wifi_down_time} seconds...")
|
|
log_with_server(
|
|
f"WiFi recovery initiated: WiFi down for {wifi_down_time} seconds",
|
|
self.hostname,
|
|
self.device_ip
|
|
)
|
|
|
|
# Stop WiFi
|
|
if not self.stop_wifi(interface):
|
|
return False
|
|
|
|
# Keep WiFi down for specified time
|
|
wait_time = wifi_down_time
|
|
while wait_time > 0:
|
|
minutes = wait_time // 60
|
|
seconds = wait_time % 60
|
|
self.logger.info(f"WiFi will restart in {minutes}m {seconds}s")
|
|
|
|
time.sleep(60) # Check every minute
|
|
wait_time -= 60
|
|
|
|
# Restart WiFi
|
|
if not self.start_wifi(interface):
|
|
return False
|
|
|
|
self.logger.info("WiFi has been restarted")
|
|
log_with_server("WiFi successfully restarted", self.hostname, self.device_ip)
|
|
|
|
# Reset failure counter
|
|
self.consecutive_failures = 0
|
|
return True
|
|
|
|
|
|
def check_server_connection(self, server_host):
|
|
"""
|
|
Check if server is reachable via ping
|
|
|
|
Args:
|
|
server_host: Server hostname or IP to ping
|
|
|
|
Returns:
|
|
bool: True if server is reachable, False otherwise
|
|
"""
|
|
try:
|
|
result = subprocess.run(
|
|
['ping', '-c', '1', '-W', '5', server_host],
|
|
capture_output=True,
|
|
timeout=10
|
|
)
|
|
return result.returncode == 0
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Ping check failed: {e}")
|
|
return False
|
|
|
|
|
|
def monitor_connection(self, server_host="10.76.140.17"):
|
|
"""
|
|
Continuously monitor server connection and manage WiFi
|
|
|
|
Args:
|
|
server_host: Server hostname/IP to monitor
|
|
"""
|
|
self.is_running = True
|
|
wifi_interface = self.get_wifi_interface()
|
|
|
|
if not wifi_interface:
|
|
self.logger.error("Cannot monitor without WiFi interface")
|
|
return
|
|
|
|
self.logger.info(f"Starting connection monitor for {server_host} on {wifi_interface}")
|
|
log_with_server(
|
|
f"Connection monitor started for {server_host}",
|
|
self.hostname,
|
|
self.device_ip
|
|
)
|
|
|
|
while self.is_running:
|
|
try:
|
|
# Check if server is reachable
|
|
if self.check_server_connection(server_host):
|
|
if self.consecutive_failures > 0:
|
|
self.consecutive_failures = 0
|
|
self.logger.info("Server connection restored")
|
|
log_with_server("Server connection restored", self.hostname, self.device_ip)
|
|
else:
|
|
self.consecutive_failures += 1
|
|
self.logger.warning(
|
|
f"Connection lost: {self.consecutive_failures}/{self.failure_threshold} failures"
|
|
)
|
|
|
|
# If threshold reached, do WiFi recovery
|
|
if self.consecutive_failures >= self.failure_threshold:
|
|
self.logger.error(
|
|
f"Server unreachable for {self.failure_threshold} pings - initiating WiFi recovery"
|
|
)
|
|
|
|
# Perform WiFi recovery
|
|
if self.reconnect_wifi(wifi_interface, self.wifi_down_time):
|
|
self.logger.info("WiFi recovery completed successfully")
|
|
else:
|
|
self.logger.error("WiFi recovery failed")
|
|
|
|
time.sleep(self.check_interval)
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error in connection monitor: {e}")
|
|
time.sleep(self.check_interval)
|
|
|
|
|
|
def start_monitoring(self, server_host="10.76.140.17"):
|
|
"""
|
|
Start background monitoring thread
|
|
|
|
Args:
|
|
server_host: Server to monitor
|
|
"""
|
|
self.monitor_thread = threading.Thread(
|
|
target=self.monitor_connection,
|
|
args=(server_host,),
|
|
daemon=True
|
|
)
|
|
self.monitor_thread.start()
|
|
self.logger.info("WiFi recovery monitor thread started")
|
|
|
|
|
|
def stop_monitoring(self):
|
|
"""Stop the monitoring thread"""
|
|
self.is_running = False
|
|
if self.monitor_thread:
|
|
self.monitor_thread.join(timeout=5)
|
|
self.logger.info("WiFi recovery monitor stopped")
|
|
|
|
|
|
# Global WiFi recovery manager instance
|
|
wifi_recovery_manager = None
|
|
|
|
|
|
def initialize_wifi_recovery(hostname, device_ip, server_host="10.76.140.17"):
|
|
"""Initialize and start WiFi recovery monitoring"""
|
|
global wifi_recovery_manager
|
|
|
|
try:
|
|
wifi_recovery_manager = WiFiRecoveryManager(
|
|
hostname=hostname,
|
|
device_ip=device_ip,
|
|
check_interval=60,
|
|
failure_threshold=5
|
|
)
|
|
wifi_recovery_manager.start_monitoring(server_host)
|
|
logging.info("WiFi recovery initialized")
|
|
return wifi_recovery_manager
|
|
|
|
except Exception as e:
|
|
logging.error(f"Failed to initialize WiFi recovery: {e}")
|
|
return None
|