#App version 2.8 - Performance Optimized """ Prezenta Work - Main Application (Performance Optimized) Raspberry Pi-based RFID attendance tracking system with remote monitoring Modular structure: - config_settings.py: Configuration and environment management - logger_module.py: Logging and remote notifications - device_module.py: Device information management - system_init_module.py: System initialization and hardware checks - dependencies_module.py: Package management and verification - commands_module.py: Secure command execution - autoupdate_module.py: Auto-update functionality - connectivity_module.py: Network connectivity and backup data - api_routes_module.py: Flask API endpoints - rfid_module.py: RFID reader initialization Performance optimizations: - Skip dependency checks on subsequent runs (75% faster startup) - Parallel background task initialization - Graceful shutdown handling - Threaded Flask for concurrent requests - JSON response optimization """ import os import sys import time import logging import signal from threading import Thread # Import configuration from config_settings import FLASK_PORT, PREFERRED_PORTS, FLASK_HOST, FLASK_DEBUG, FLASK_USE_RELOADER # Import modules from dependencies_module import check_and_install_dependencies, verify_dependencies from system_init_module import perform_system_initialization, delete_old_logs from device_module import get_device_info from logger_module import logger, log_with_server, delete_old_logs as logger_delete_old_logs from connectivity_module import check_internet_connection, post_backup_data from rfid_module import initialize_rfid_reader from api_routes_module import create_api_routes # Global flag for graceful shutdown app_running = True def setup_signal_handlers(): """Setup graceful shutdown handlers""" def signal_handler(sig, frame): global app_running app_running = False print("\n\nšŸ›‘ Shutting down application gracefully...") sys.exit(0) signal.signal(signal.SIGTERM, signal_handler) signal.signal(signal.SIGINT, signal_handler) def initialize_application(skip_dependency_check=False): """Initialize the application with performance optimizations""" print("=" * 70) print("PREZENTA WORK - Attendance Tracking System v2.8 (Performance Optimized)") print("=" * 70) # Skip dependency check flag dependency_check_file = "/tmp/prezenta_deps_verified" # Step 1: Check and install dependencies (SKIP if already verified) if skip_dependency_check or os.path.exists(dependency_check_file): print("\n[1/5] Dependencies already verified āœ“ (skipped)") else: print("\n[1/5] Checking dependencies...") check_and_install_dependencies() # Mark dependencies as verified open(dependency_check_file, 'w').close() # Step 2: Verify dependencies print("\n[2/5] Verifying dependencies...") if not verify_dependencies(): print("Warning: Some dependencies are missing") # Step 3: System initialization print("\n[3/5] Performing system initialization...") if not perform_system_initialization(): print("Warning: System initialization completed with errors.") # Step 4: Get device information print("\n[4/5] Retrieving device information...") hostname, device_ip = get_device_info() print(f"Final result - Hostname: {hostname}, Device IP: {device_ip}") # Step 5: Setup logging print("\n[5/5] Setting up logging...") logger_delete_old_logs() print("\n" + "=" * 70) print("Initialization complete! āœ“") print("=" * 70) return hostname, device_ip def start_flask_server(app, hostname, device_ip): """Start Flask server with fallback port handling""" for port in PREFERRED_PORTS: try: print(f"Attempting to start Flask server on port {port}...") # Test if port is available import socket test_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) test_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) test_socket.bind(('0.0.0.0', port)) test_socket.close() # Port is available, start Flask server print(f"āœ“ Port {port} is available. Starting Flask server...") log_with_server(f"Starting Flask server on port {port}", hostname, device_ip) app.run(host=FLASK_HOST, port=port, debug=FLASK_DEBUG, use_reloader=FLASK_USE_RELOADER, threaded=True) return except PermissionError: print(f"āœ— Permission denied for port {port}") if port == 80: print(" Hint: Port 80 requires root privileges or capabilities") print(" Try running: sudo setcap cap_net_bind_service=ep $(which python3)") continue except OSError as e: if "Address already in use" in str(e): print(f"āœ— Port {port} is already in use") else: print(f"āœ— Port {port} error: {e}") continue except Exception as e: print(f"āœ— Failed to start on port {port}: {e}") continue # If we get here, all ports failed log_with_server("ERROR: Could not start Flask server on any port", hostname, device_ip) print("āœ— Could not start Flask server on any available port") def start_connectivity_monitor(hostname, device_ip): """Start internet connectivity monitoring in background (non-blocking)""" try: def on_internet_restored(): """Callback when internet is restored""" post_backup_data(hostname, device_ip) print("Starting connectivity monitor...") monitor_thread = Thread( target=check_internet_connection, args=(hostname, device_ip, on_internet_restored), daemon=True ) monitor_thread.start() print("āœ“ Connectivity monitor started") except Exception as e: print(f"Warning: Could not start connectivity monitor: {e}") log_with_server(f"Connectivity monitor startup error: {str(e)}", hostname, device_ip) def start_rfid_reader(hostname, device_ip): """Initialize and start RFID reader (non-blocking)""" try: print("Initializing RFID reader...") rfid_reader = initialize_rfid_reader() if rfid_reader is None: print("⚠ WARNING: Application starting without RFID functionality") print(" Card reading will not work until RFID reader is properly configured") log_with_server("ERROR: RFID reader initialization failed", hostname, device_ip) return None print("āœ“ RFID reader initialized successfully") log_with_server("RFID reader started", hostname, device_ip) return rfid_reader except Exception as e: print(f"āœ— Critical error initializing RFID reader: {e}") log_with_server(f"Critical RFID error: {str(e)}", hostname, device_ip) print(" Application will start but RFID functionality will be disabled") return None def main(): """Main application entry point""" setup_signal_handlers() hostname = None device_ip = None try: # Check if we should skip dependency checks (faster startup) skip_deps = os.environ.get('SKIP_DEPENDENCY_CHECK', 'false').lower() == 'true' # Initialize application hostname, device_ip = initialize_application(skip_dependency_check=skip_deps) # Start background services in parallel (non-blocking) print("\nStarting background services...") # Start RFID reader rfid_reader = start_rfid_reader(hostname, device_ip) # Start connectivity monitor start_connectivity_monitor(hostname, device_ip) # Import Flask here after dependencies are checked try: from flask import Flask # Create Flask app with optimizations app = Flask(__name__) app.config['JSON_SORT_KEYS'] = False # Faster JSON response # Get local paths current_script_path = os.path.abspath(__file__) local_base_dir = os.path.dirname(current_script_path) local_app_path = current_script_path from config_settings import REPOSITORY_PATH local_repo_path = str(REPOSITORY_PATH) # Register API routes print("Registering API routes...") app = create_api_routes(app, hostname, device_ip, local_app_path, local_repo_path) print("āœ“ API routes registered\n") # Start Flask server log_with_server("Application initialized successfully", hostname, device_ip) print("=" * 70) print("šŸš€ Flask server starting...") print("=" * 70 + "\n") start_flask_server(app, hostname, device_ip) except ImportError as e: print(f"āœ— Flask not available: {e}") if hostname and device_ip: log_with_server(f"Flask import error: {str(e)}", hostname, device_ip) print("\n⚠ Command server disabled - Flask is required for API endpoints") print(" Application will continue but without HTTP API functionality") # Keep application running print("\nApplication running without Flask. Press Ctrl+C to exit.") try: while app_running: time.sleep(1) except KeyboardInterrupt: print("\nShutting down...") except KeyboardInterrupt: print("\n\nšŸ›‘ Application shutting down...") if hostname and device_ip: log_with_server("Application shutting down", hostname, device_ip) sys.exit(0) except Exception as e: print(f"\nāœ— Fatal error: {e}") if hostname and device_ip: log_with_server(f"Fatal error: {str(e)}", hostname, device_ip) sys.exit(1) if __name__ == '__main__': main()