2025-08-12 07:21:41 +08:00

323 lines
13 KiB
Rust

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<JoinHandle<()>>,
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(_)));
}
}