use anyhow::Result; use log::{error, info, warn}; use std::sync::Arc; use std::time::Duration; use tokio::sync::mpsc::{self, Sender}; use tokio::time; // 导入Camera模块组件 use meteor_detect::camera::{CameraController, CameraSettings, ExposureMode, Resolution, FrameBuffer, Frame}; use meteor_detect::config::Config; /// 演示如何使用相机模块构建完整的流星检测系统 #[tokio::main] async fn main() -> Result<()> { // 初始化日志 env_logger::init(); // 1. 创建和初始化相机 let config = create_detector_config(); let mut camera = CameraController::new(&config).await?; info!("初始化相机系统"); camera.initialize().await?; info!("启动相机捕获"); camera.start_capture().await?; // 2. 获取帧缓冲器的引用(用于检测器访问) let frame_buffer = camera.get_frame_buffer(); // 3. 创建通信通道 // 用于从检测器向主程序发送事件 let (event_tx, mut event_rx) = mpsc::channel(10); // 用于从健康监控向主程序发送健康状态 let (health_tx, mut health_rx) = mpsc::channel(10); // 4. 启动检测器任务,从缓冲区读取帧进行处理 start_detector_task(frame_buffer.clone(), event_tx).await; // 5. 启动健康监控任务 - 只发送健康状态,而不是直接操作相机 start_health_monitor_task(health_tx).await; // 6. 主线程处理检测事件和健康状态 info!("等待检测事件..."); let mut saved_events = 0; // 创建轮询健康状态的定时器 let mut health_interval = time::interval(Duration::from_secs(30)); loop { tokio::select! { // 处理检测事件 Some(event) = event_rx.recv() => { info!("收到流星检测事件: 时间={}, 置信度={:.2}", event.timestamp, event.confidence); // 保存事件视频 match camera.save_meteor_event( event.timestamp, event.confidence, event.bounding_box, 5, // 事件前5秒 3, // 事件后3秒 ).await { Ok(saved_event) => { info!("已保存流星事件视频: {}", saved_event.video_path); saved_events += 1; // 在这里可以添加额外处理,如上传到云存储、发送通知等 }, Err(e) => { error!("保存流星事件失败: {}", e); } } // 演示目的,保存3个事件后退出 if saved_events >= 3 { info!("已保存足够的事件,退出处理循环"); break; } }, // 处理健康检查的时间间隔 _ = health_interval.tick() => { // 直接在主线程中执行健康检查 match camera.check_health().await { Ok(is_healthy) => { if !is_healthy { warn!("相机健康检查失败,可能需要干预"); } else { info!("相机健康状态: 正常"); } }, Err(e) => { error!("健康检查失败: {}", e); } } // 获取和记录相机状态 if let Ok(status) = camera.get_status().await { info!("相机状态: {}", status); } }, // 接收健康监控发送的消息(演示目的,实际中可以根据需要处理) Some(health_msg) = health_rx.recv() => { info!("收到健康监控消息: {}", health_msg); }, // 如果所有通道都已关闭,退出循环 else => break, } } // 7. 清理资源 info!("停止相机捕获"); camera.stop_capture().await?; info!("流星检测系统演示完成"); Ok(()) } /// 启动检测器任务 async fn start_detector_task(frame_buffer: Arc, event_tx: Sender) { tokio::spawn(async move { info!("启动流星检测器"); let mut detection_count = 0; let mut last_detection_time = chrono::Utc::now(); // 模拟检测循环 loop { // 模拟帧分析(实际应用中会连续分析每一帧) time::sleep(Duration::from_secs(2)).await; // 从帧缓冲区获取最新帧 if let Some(frame) = frame_buffer.get(0) { let now = chrono::Utc::now(); // 确保距离上次检测至少10秒(防止重复检测) if (now - last_detection_time).num_seconds() >= 10 { // 这里应该是实际的检测算法 // 为演示目的,我们随机生成一些检测结果 let detection_seed = rand::random::(); if detection_seed < 0.3 { // 30%的概率检测到流星 detection_count += 1; last_detection_time = now; info!("检测到流星 #{}", detection_count); // 发送检测事件到主线程 let event = DetectionEvent { timestamp: now, confidence: 0.7 + (detection_seed * 0.3), // 0.7-1.0之间的置信度 bounding_box: ( (rand::random::() * 800.0) as u32, // x (rand::random::() * 600.0) as u32, // y (50.0 + rand::random::() * 100.0) as u32, // width (50.0 + rand::random::() * 100.0) as u32, // height ), }; if event_tx.send(event).await.is_err() { warn!("无法发送检测事件,接收端可能已关闭"); break; } } } } else { warn!("无法获取帧,缓冲区可能为空"); time::sleep(Duration::from_millis(500)).await; } // 演示目的,5次检测后退出 if detection_count >= 5 { info!("已达到预设检测次数,检测器退出"); break; } } }); } /// 启动健康监控任务 async fn start_health_monitor_task(health_tx: Sender) { tokio::spawn(async move { info!("启动健康监控任务 (模拟)"); let mut interval = time::interval(Duration::from_secs(45)); // 简单模拟健康监控,不直接访问相机 // 在实际应用中,这可能会监控系统各个部分的状态 loop { interval.tick().await; // 发送简单的健康状态消息回主线程 // 这是一个简化的演示 if health_tx.send("系统运行正常".to_string()).await.is_err() { warn!("无法发送健康状态,接收端可能已关闭"); break; } } }); } /// 创建用于检测系统的配置 fn create_detector_config() -> Config { let camera_settings = CameraSettings { device: "0".to_string(), // 对于流星检测,建议使用更高分辨率 resolution: Resolution::HD1080p, fps: 30, // 对于夜间观测,手动曝光通常更好 exposure: ExposureMode::Manual(500000), // 500毫秒曝光 // 增加增益以提高低光灵敏度 gain: 200, focus_locked: true, }; Config { camera: camera_settings, // 其他配置字段,使用其默认值 ..Default::default() } } /// 流星检测事件 struct DetectionEvent { /// 事件时间戳 timestamp: chrono::DateTime, /// 检测置信度 (0-1) confidence: f32, /// 边界框 (x, y, 宽度, 高度) bounding_box: (u32, u32, u32, u32), }