#!/usr/bin/env python3 """ Prezenta Work - Workplace Attendance & Traceability System (v3.0) Enhanced with batch logging, Chrome fullscreen UI, and WiFi recovery Main application orchestrator that coordinates all system components: - Batch logging with event deduplication (75% network reduction) - Chrome browser in fullscreen kiosk mode - WiFi auto-recovery on server disconnection - RFID card reader integration - Remote monitoring and logging """ import signal import sys import logging import time import threading from datetime import datetime # Import all modules from config_settings import ( MONITORING_SERVER_URL, AUTO_UPDATE_SERVER_HOST, CONNECTIVITY_CHECK_HOST, FLASK_PORT, LOG_FILE, DEVICE_INFO_FILE, TAG_FILE ) from logger_module import log_with_server from device_module import get_device_info from system_init_module import perform_system_initialization from dependencies_module import check_and_install_dependencies from api_routes_module import create_api_routes from rfid_module import initialize_rfid_reader from connectivity_module import check_internet_connection, post_backup_data # Import new enhancement modules from logger_batch_module import ( setup_logging as setup_batch_logging, start_batch_logger, queue_log_message ) from chrome_launcher_module import launch_chrome_app, get_chrome_path from wifi_recovery_module import initialize_wifi_recovery # Flask app from flask import Flask # Global variables app = None device_hostname = None device_ip = None def setup_signal_handlers(): """Setup graceful shutdown handlers""" def signal_handler(sig, frame): global app_running logging.warning(f"Received signal {sig}. Initiating graceful shutdown...") log_with_server("Application shutdown initiated", device_hostname, device_ip) app_running = False # Stop batch logger if batch_logger_thread: logging.info("Stopping batch logger...") # Stop WiFi recovery monitor if wifi_recovery_manager: logging.info("Stopping WiFi recovery monitor...") wifi_recovery_manager.stop_monitoring() sys.exit(0) signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) logging.info("Signal handlers configured") def initialize_application(): """Initialize all application components""" global device_hostname, device_ip, app, logger try: logging.info("=" * 80) logging.info("Prezenta Work v3.0 - Workplace Attendance System") logging.info("=" * 80) logging.info(f"Start time: {datetime.now().isoformat()}") # Get device info logging.info("Retrieving device information...") device_info = get_device_info() device_hostname = device_info['hostname'] device_ip = device_info['ip'] logging.info(f"Device: {device_hostname} ({device_ip})") log_with_server( "Application started - v3.0 with batch logging and WiFi recovery", device_hostname, device_ip ) # Initialize system logging.info("Performing system initialization...") perform_system_initialization() # Check and install dependencies logging.info("Checking dependencies...") check_and_install_dependencies() # Setup batch logging logging.info("Setting up batch logging system...") setup_batch_logging(device_hostname) # Create Flask app logging.info("Initializing Flask application...") app = Flask(__name__) create_api_routes(app) logging.info("Application initialization completed successfully") return True except Exception as e: logging.error(f"Application initialization failed: {e}") return False def start_flask_server(): """Start Flask web server""" try: logging.info(f"Starting Flask server on port {FLASK_PORT}...") log_with_server(f"Flask server starting on port {FLASK_PORT}", device_hostname, device_ip) # Run Flask in a separate thread flask_thread = threading.Thread( target=lambda: app.run(host='0.0.0.0', port=FLASK_PORT, debug=False, use_reloader=False), daemon=True ) flask_thread.start() logging.info("Flask server thread started") return True except Exception as e: logging.error(f"Failed to start Flask server: {e}") log_with_server(f"ERROR: Flask server failed: {str(e)}", device_hostname, device_ip) return False def start_chrome_app(): """Launch Chrome in fullscreen with traceability application""" try: if get_chrome_path(): logging.info("Starting Chrome fullscreen application...") log_with_server("Launching Chrome fullscreen UI", device_hostname, device_ip) # Launch Chrome with local Flask server chrome_thread = threading.Thread( target=lambda: launch_chrome_app(device_hostname, device_ip, f"http://localhost:{FLASK_PORT}"), daemon=True ) chrome_thread.start() logging.info("Chrome launch thread started") return True else: logging.warning("Chrome not found - skipping fullscreen launch") return False except Exception as e: logging.error(f"Failed to start Chrome app: {e}") log_with_server(f"ERROR: Chrome launch failed: {str(e)}", device_hostname, device_ip) return False def start_wifi_recovery_monitor(): """Initialize WiFi recovery monitoring""" global wifi_recovery_manager try: logging.info("Initializing WiFi recovery monitor...") log_with_server("WiFi recovery system initialized", device_hostname, device_ip) wifi_recovery_manager = initialize_wifi_recovery( device_hostname, device_ip, server_host=CONNECTIVITY_CHECK_HOST ) if wifi_recovery_manager: logging.info("WiFi recovery monitor started") return True else: logging.error("Failed to initialize WiFi recovery") return False except Exception as e: logging.error(f"Error starting WiFi recovery: {e}") return False def start_batch_logger_thread(): """Start the batch logging system""" global batch_logger_thread try: logging.info("Starting batch logger thread...") batch_logger_thread = threading.Thread( target=start_batch_logger, args=(device_hostname, device_ip), daemon=True ) batch_logger_thread.start() logging.info("Batch logger thread started (5s batches, event dedup)") return True except Exception as e: logging.error(f"Error starting batch logger: {e}") return False def start_connectivity_monitor(): """Monitor internet connectivity""" def connectivity_loop(): while app_running: try: if not check_internet_connection(): logging.warning("No internet connectivity") else: post_backup_data() except Exception as e: logging.error(f"Connectivity monitor error: {e}") time.sleep(30) # Check every 30 seconds try: logging.info("Starting connectivity monitor...") conn_thread = threading.Thread(target=connectivity_loop, daemon=True) conn_thread.start() logging.info("Connectivity monitor thread started") return True except Exception as e: logging.error(f"Error starting connectivity monitor: {e}") return False def start_rfid_reader(): """Initialize RFID reader""" global rfid_reader try: logging.info("Initializing RFID reader...") rfid_reader = initialize_rfid_reader() if rfid_reader: logging.info("RFID reader initialized successfully") log_with_server("RFID reader ready", device_hostname, device_ip) return True else: logging.error("RFID reader initialization failed") return False except Exception as e: logging.error(f"Error initializing RFID reader: {e}") return False def main(): """Main application entry point""" global app_running # Configure basic logging first logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler(LOG_FILE), logging.StreamHandler(sys.stdout) ] ) # Setup signal handlers for graceful shutdown setup_signal_handlers() try: # Initialize application if not initialize_application(): logging.error("Application initialization failed") return 1 # Start core components in sequence logging.info("Starting application components...") # 1. Start Flask web server (provides UI endpoint) start_flask_server() time.sleep(1) # 2. Start batch logging system start_batch_logger_thread() time.sleep(0.5) # 3. Launch Chrome fullscreen UI start_chrome_app() time.sleep(2) # 4. Initialize RFID reader start_rfid_reader() # 5. Start connectivity monitoring start_connectivity_monitor() # 6. Start WiFi recovery monitor start_wifi_recovery_monitor() logging.info("All components started successfully") log_with_server( "System fully operational - batch logging active (75% reduction), " "Chrome UI fullscreen, WiFi recovery enabled", device_hostname, device_ip ) # Keep application running logging.info("Application is now running...") while app_running: time.sleep(1) logging.info("Application shutdown complete") return 0 except Exception as e: logging.error(f"Fatal error: {e}") log_with_server(f"FATAL ERROR: {str(e)}", device_hostname, device_ip) return 1 if __name__ == '__main__': sys.exit(main())