""" System initialization and hardware checks Handles first-run setup and hardware validation """ import os import sys import subprocess import stat import pwd import grp from config_settings import SERIAL_DEVICES, GPIO_DEVICES def check_system_requirements(): """Check basic system requirements""" print("Checking system requirements...") try: # Check if running on supported OS if sys.platform not in ['linux', 'linux2']: print("⚠ Warning: This application is designed for Linux systems") return False # Check Python version if sys.version_info < (3, 7): print("✗ Python 3.7+ required") return False print(f"✓ Python {sys.version_info.major}.{sys.version_info.minor} detected") return True except Exception as e: print(f"✗ Error checking system requirements: {e}") return False def check_port_capabilities(): """Check if the application can bind to port 80""" print("Checking port 80 capabilities...") try: # Check if we're running as root if os.geteuid() == 0: print("✓ Running as root - port 80 access available") return True # Check if capabilities are set python_path = sys.executable result = subprocess.run(['getcap', python_path], capture_output=True, text=True) if 'cap_net_bind_service=ep' in result.stdout: print("✓ Port binding capabilities already set") return True # Try to set capabilities print("Setting up port 80 binding capabilities...") setup_script = './setup_port_capability.sh' if os.path.exists(setup_script): result = subprocess.run(['sudo', 'bash', setup_script], capture_output=True, text=True) if result.returncode == 0: print("✓ Port capabilities set successfully") return True else: print(f"✗ Failed to set capabilities: {result.stderr}") except Exception as e: print(f"Warning: Could not check port capabilities: {e}") print("Warning: Port 80 may not be accessible. App will try to run on default port.") return False def check_hardware_interfaces(): """Check hardware interfaces (UART/Serial) for RFID reader""" print("Checking hardware interfaces...") available_devices = [] for device in SERIAL_DEVICES: if os.path.exists(device): try: with open(device, 'r'): pass available_devices.append(device) print(f"✓ Serial device available: {device}") except PermissionError: print(f"✗ Permission denied for {device}. Adding user to dialout group...") try: username = pwd.getpwuid(os.getuid()).pw_name subprocess.run(['sudo', 'usermod', '-a', '-G', 'dialout', username], capture_output=True, text=True) print(f"✓ User {username} added to dialout group (reboot may be required)") available_devices.append(device) except Exception as e: print(f"✗ Failed to add user to dialout group: {e}") except Exception as e: print(f"Warning: Could not test {device}: {e}") if not available_devices: print("✗ No serial devices found. RFID reader may not work.") try: config_file = '/boot/config.txt' if os.path.exists(config_file): print("Attempting to enable UART in Raspberry Pi config...") result = subprocess.run(['sudo', 'raspi-config', 'nonint', 'do_serial', '0'], capture_output=True, text=True) if result.returncode == 0: print("✓ UART enabled in config (reboot required)") else: print("Warning: Could not enable UART automatically") except Exception as e: print(f"Warning: Could not configure UART: {e}") return False return True def initialize_gpio_permissions(): """Set up GPIO permissions for LED control""" print("Setting up GPIO permissions...") try: username = pwd.getpwuid(os.getuid()).pw_name # Check if gpio group exists try: grp.getgrnam('gpio') subprocess.run(['sudo', 'usermod', '-a', '-G', 'gpio', username], capture_output=True, text=True) print(f"✓ User {username} added to gpio group") except KeyError: print("Warning: gpio group not found - GPIO access may be limited") # Set up GPIO access via /dev/gpiomem if available for device in GPIO_DEVICES: if os.path.exists(device): print(f"✓ GPIO device available: {device}") return True print("Warning: No GPIO devices found") return False except Exception as e: print(f"Warning: Could not set up GPIO permissions: {e}") return False def check_network_connectivity(): """Check network connectivity and DNS resolution""" print("Checking network connectivity...") try: # Test basic connectivity result = subprocess.run(['ping', '-c', '1', '8.8.8.8'], capture_output=True, text=True, timeout=5) if result.returncode == 0: print("✓ Internet connectivity available") # Test DNS resolution try: import socket socket.gethostbyname('google.com') print("✓ DNS resolution working") return True except socket.gaierror: print("✗ DNS resolution failed") return False else: print("✗ No internet connectivity") return False except subprocess.TimeoutExpired: print("✗ Network timeout") return False except Exception as e: print(f"Warning: Could not test network: {e}") return False def create_required_files(): """Create required data files with defaults if they don't exist""" print("Checking required files...") from config_settings import ID_MASA_FILE, TAG_FILE, DATA_DIR required_files = { str(ID_MASA_FILE): "unknown", str(TAG_FILE): "" } for file_path, default_content in required_files.items(): try: if not os.path.exists(file_path): os.makedirs(os.path.dirname(file_path), exist_ok=True) with open(file_path, 'w') as f: f.write(default_content) print(f"✓ Created default file: {file_path}") else: print(f"✓ File exists: {file_path}") except Exception as e: print(f"✗ Failed to create file {file_path}: {e}") # Set file permissions try: for file_path in required_files.keys(): if os.path.exists(file_path): os.chmod(file_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH) print("✓ File permissions set correctly") except Exception as e: print(f"Warning: Could not set file permissions: {e}") return True def perform_system_initialization(): """Perform complete system initialization for first run""" print("=" * 60) print("SYSTEM INITIALIZATION - Preparing for first run") print("=" * 60) initialization_steps = [ ("System Requirements", check_system_requirements), ("File Creation", create_required_files), ("Port Capabilities", check_port_capabilities), ("Hardware Interfaces", check_hardware_interfaces), ("GPIO Permissions", initialize_gpio_permissions), ("Network Connectivity", check_network_connectivity) ] success_count = 0 total_steps = len(initialization_steps) for step_name, step_function in initialization_steps: print(f"\n--- {step_name} ---") try: if step_function(): success_count += 1 print(f"✓ {step_name} completed successfully") else: print(f"⚠ {step_name} completed with warnings") except Exception as e: print(f"✗ {step_name} failed: {e}") print("\n" + "=" * 60) print(f"INITIALIZATION COMPLETE: {success_count}/{total_steps} steps successful") print("=" * 60) if success_count < total_steps: print("Warning: Some initialization steps failed. Application may have limited functionality.") return success_count >= (total_steps - 1) # Allow one failure