Files
prezenta_work/app.py

335 lines
10 KiB
Python

#!/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())