use anyhow::Result; use std::time::Duration; use tokio::task::JoinHandle; use tokio::time::sleep; use crate::events::{EventBus, SystemEvent, SystemStartedEvent}; use crate::camera::{CameraController, CameraConfig}; use crate::config::{load_camera_config, load_storage_config, load_communication_config, ConfigManager}; use crate::detection::{DetectionController, DetectionConfig}; use crate::storage::{StorageController, StorageConfig}; use crate::communication::{CommunicationController, CommunicationConfig}; use crate::api::ApiClient; use crate::memory_monitor::{MemoryMonitor, record_frame_processed}; /// Core application coordinator that manages the event bus and background tasks pub struct Application { event_bus: EventBus, background_tasks: Vec>, memory_monitor: MemoryMonitor, } impl Application { /// Create a new Application instance with an event bus pub fn new(event_bus_capacity: usize) -> Self { Self { event_bus: EventBus::new(event_bus_capacity), background_tasks: Vec::new(), memory_monitor: MemoryMonitor::new(), } } /// Start the application and run the main event loop pub async fn run(&mut self) -> Result<()> { println!("🚀 Starting Meteor Edge Client Application..."); // Create a test subscriber to verify event flow let mut test_subscriber = self.event_bus.subscribe(); // Spawn a background task to handle test events let test_handle = tokio::spawn(async move { println!("📡 Test subscriber started, waiting for events..."); let mut system_started = false; let mut frame_count = 0; while let Ok(event) = test_subscriber.recv().await { match event.as_ref() { SystemEvent::SystemStarted(system_event) => { println!("✅ Received SystemStartedEvent!"); println!(" Timestamp: {}", system_event.timestamp); println!(" Version: {}", system_event.version); println!(" Event verification successful! 🎉"); system_started = true; } SystemEvent::FrameCaptured(frame_event) => { frame_count += 1; // Record memory optimization metrics record_frame_processed(frame_event.data_size(), 3); // Assume 3 subscribers if frame_count <= 5 || frame_count % 30 == 0 { println!("📸 Received FrameCapturedEvent #{}", frame_event.frame_id); println!(" Timestamp: {}", frame_event.timestamp); let (width, height) = frame_event.dimensions(); println!(" Resolution: {}x{}", width, height); println!(" Data size: {} bytes (zero-copy!)", frame_event.data_size()); println!(" Format: {:?}", frame_event.frame_data.format); } // Exit after receiving some frames for demo if frame_count >= 10 { println!("🎬 Received {} frames, test subscriber stopping...", frame_count); break; } } SystemEvent::MeteorDetected(meteor_event) => { println!("🌟 METEOR ALERT! Frame #{}, Confidence: {:.2}%", meteor_event.trigger_frame_id, meteor_event.confidence_score * 100.0 ); println!(" Algorithm: {}", meteor_event.algorithm_name); println!(" Detected at: {}", meteor_event.detection_timestamp); } SystemEvent::EventPackageArchived(archive_event) => { println!("📦 EVENT ARCHIVED! ID: {}, Size: {} bytes", archive_event.event_id, archive_event.archive_size_bytes ); println!(" Directory: {:?}", archive_event.event_directory_path); println!(" Frames: {}", archive_event.total_frames); } } } println!("🔚 Test subscriber finished"); }); self.background_tasks.push(test_handle); // Give the subscriber a moment to be ready sleep(Duration::from_millis(10)).await; // Publish the SystemStartedEvent to verify the event flow println!("📢 Publishing SystemStartedEvent..."); let system_started_event = SystemStartedEvent::new(); self.event_bus.publish_system_started(system_started_event)?; println!(" Event published successfully!"); // Initialize and start camera controller println!("🎥 Initializing camera controller..."); let camera_config = load_camera_config()?; let mut camera_controller = CameraController::new(camera_config, self.event_bus.clone()); // Spawn camera controller in background task let camera_handle = tokio::spawn(async move { if let Err(e) = camera_controller.run().await { eprintln!("❌ Camera controller error: {}", e); } }); self.background_tasks.push(camera_handle); // Start memory monitoring reporting println!("📊 Starting memory optimization monitoring..."); let memory_handle = tokio::spawn(async move { use crate::memory_monitor::GLOBAL_MEMORY_MONITOR; GLOBAL_MEMORY_MONITOR.start_reporting(30).await; // Report every 30 seconds }); self.background_tasks.push(memory_handle); // Initialize and start detection controller println!("🔍 Initializing detection controller..."); let detection_config = DetectionConfig::default(); let mut detection_controller = DetectionController::new(detection_config, self.event_bus.clone()); // Spawn detection controller in background task let detection_handle = tokio::spawn(async move { if let Err(e) = detection_controller.run().await { eprintln!("❌ Detection controller error: {}", e); } }); self.background_tasks.push(detection_handle); // Initialize and start storage controller println!("💾 Initializing storage controller..."); let storage_config = load_storage_config()?; let mut storage_controller = match StorageController::new(storage_config, self.event_bus.clone()) { Ok(controller) => controller, Err(e) => { eprintln!("❌ Failed to create storage controller: {}", e); return Err(e); } }; // Spawn storage controller in background task let storage_handle = tokio::spawn(async move { if let Err(e) = storage_controller.run().await { eprintln!("❌ Storage controller error: {}", e); } }); self.background_tasks.push(storage_handle); // Initialize and start communication controller println!("📡 Initializing communication controller..."); let communication_config = load_communication_config()?; let heartbeat_config = communication_config.clone(); // Clone before moving let mut communication_controller = match CommunicationController::new(communication_config, self.event_bus.clone()) { Ok(controller) => controller, Err(e) => { eprintln!("❌ Failed to create communication controller: {}", e); return Err(e); } }; // Spawn communication controller in background task let communication_handle = tokio::spawn(async move { if let Err(e) = communication_controller.run().await { eprintln!("❌ Communication controller error: {}", e); } }); self.background_tasks.push(communication_handle); // Initialize and start heartbeat task println!("💓 Initializing heartbeat task..."); let heartbeat_handle = tokio::spawn(async move { if let Err(e) = Self::run_heartbeat_task(heartbeat_config).await { eprintln!("❌ Heartbeat task error: {}", e); } }); self.background_tasks.push(heartbeat_handle); // Run the main application loop println!("🔄 Starting main application loop..."); self.main_loop().await?; Ok(()) } /// Main application loop - this will eventually coordinate all modules async fn main_loop(&mut self) -> Result<()> { println!("⏳ Main loop running... (will exit after 10 seconds for demo)"); // For now, just wait a bit to allow the camera to capture frames and test subscriber to process events sleep(Duration::from_secs(10)).await; println!("🛑 Stopping application..."); // Wait for all background tasks to complete for task in self.background_tasks.drain(..) { if let Err(e) = task.await { eprintln!("❌ Background task error: {}", e); } } println!("✅ Application stopped successfully"); Ok(()) } /// Get a reference to the event bus (for other modules to use) pub fn event_bus(&self) -> &EventBus { &self.event_bus } /// Get the number of active subscribers to the event bus pub fn subscriber_count(&self) -> usize { self.event_bus.subscriber_count() } /// Background task for sending heartbeat signals to the backend async fn run_heartbeat_task(config: CommunicationConfig) -> Result<()> { println!("💓 Starting heartbeat task..."); println!(" Heartbeat interval: {}s", config.heartbeat_interval_seconds); let api_client = ApiClient::new(config.api_base_url.clone()); let config_manager = ConfigManager::new(); loop { // Wait for the configured interval sleep(Duration::from_secs(config.heartbeat_interval_seconds)).await; // Check if device is registered and has configuration if !config_manager.config_exists() { println!("⚠️ No device configuration found, skipping heartbeat"); continue; } let device_config = match config_manager.load_config() { Ok(config) => config, Err(e) => { eprintln!("❌ Failed to load device configuration: {}", e); continue; } }; // Skip heartbeat if device is not registered if !device_config.registered { println!("⚠️ Device not registered, skipping heartbeat"); continue; } // Skip heartbeat if no JWT token is available let jwt_token = match device_config.jwt_token { Some(token) => token, None => { eprintln!("❌ No JWT token available for heartbeat authentication"); continue; } }; // Send heartbeat match api_client.send_heartbeat(device_config.hardware_id, jwt_token).await { Ok(_) => { println!("✅ Heartbeat sent successfully"); } Err(e) => { eprintln!("❌ Heartbeat failed: {}", e); // Continue the loop - don't crash on heartbeat failures } } } } } #[cfg(test)] mod tests { use super::*; use tokio::time::{timeout, Duration}; #[tokio::test] async fn test_application_creation() { let app = Application::new(100); assert_eq!(app.subscriber_count(), 0); } #[tokio::test] async fn test_application_event_bus_access() { let app = Application::new(100); // Test that we can access the event bus let event_bus = app.event_bus(); let mut receiver = event_bus.subscribe(); // Verify subscriber count increased assert_eq!(app.subscriber_count(), 1); // Test publishing through the app's event bus let test_event = SystemStartedEvent::new(); event_bus.publish_system_started(test_event.clone()).unwrap(); // Verify we can receive the event let received = timeout(Duration::from_millis(100), receiver.recv()) .await .expect("Should receive event") .unwrap(); assert!(matches!(received, SystemEvent::SystemStarted(_))); } }