update ignore

This commit is contained in:
lenn
2026-04-07 18:06:46 +08:00
parent 770d713d03
commit 0d3266c95a
344 changed files with 1900 additions and 296 deletions

View File

@@ -1,25 +1,16 @@
// src-tauri/src/commands/calibration.rs
use crate::commands::serial::SerialConnectionState;
use crate::serial_core::calibration_session::{CalibrationProgress, CalibrationSession};
use crate::serial_core::codecs::tactile_a::TactileACsvExporter;
use crate::commands::serial::{CalibrationRuntime, SerialConnectionState};
use crate::serial_core::calibration_session::{
CalibrationProgress, CalibrationSession, SharedCalibrationSession,
};
use crate::serial_core::error::SerialError;
use crate::serial_core::record::{write_csv, CsvExporter};
use crate::serial_core::serial::{run_serial_with_calibration, PollMode, TactileAPollRequester};
use log::info;
use crate::serial_core::serial::run_serial_with_calibration;
use serde::Serialize;
use std::fs::File;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use tauri::{async_runtime::JoinHandle, AppHandle, Manager, State};
use std::time::Instant;
use tauri::{AppHandle, Manager, State};
use tokio_serial::SerialPortBuilderExt;
use tokio_util::sync::CancellationToken;
const DEFAULT_TACTILE_COLS: usize = 7;
const DEFAULT_TACTILE_ROWS: usize = 12;
const DEFAULT_TACTILE_POLL_INTERVAL_MS: u64 = 10;
const DEFAULT_TACTILE_REPLY_TIMEOUT_MS: u64 = 140;
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CalibrationResponse {
@@ -28,9 +19,11 @@ pub struct CalibrationResponse {
pub progress: Option<CalibrationProgress>,
}
struct CalibrationSessionData {
cancel: CancellationToken,
task: JoinHandle<()>,
fn snapshot_progress(
session: &SharedCalibrationSession,
) -> Result<CalibrationProgress, SerialError> {
let session = session.lock().map_err(|_| SerialError::StateError)?;
Ok(session.get_progress())
}
#[tauri::command]
@@ -39,111 +32,170 @@ pub async fn serial_calibrate_with_coarse(
port: String,
target_frames: usize,
max_rounds: usize,
round_interval_ms: u64,
state: State<'_, SerialConnectionState>,
) -> Result<CalibrationResponse, SerialError> {
let port_name = port.trim().to_string();
if port_name.is_empty() {
if port_name.is_empty() || target_frames == 0 || max_rounds == 0 {
return Err(SerialError::InvalidConfig);
}
// 检查是否有活跃的标定会话
{
let calibration_session = state
.calibration_session
.lock()
.map_err(|_| SerialError::StateError)?;
if calibration_session.is_some() {
return Err(SerialError::AlreadyConnected);
}
if state.has_active_serial_session()? || state.has_active_calibration()? {
return Err(SerialError::AlreadyConnected);
}
// 创建新的标定会话
let mut session = CalibrationSession::new(target_frames, max_rounds);
let mut session = CalibrationSession::new(target_frames, max_rounds, round_interval_ms);
session.start();
let session = Arc::new(Mutex::new(session));
let progress = snapshot_progress(&session)?;
let cancel = CancellationToken::new();
let session_started_at = Instant::now();
let task_cancel = cancel.clone();
let task_app = app.clone();
// let task_port_name = port_name.clone();
let progress = session.get_progress();
let session_for_state = session.clone();
let task_session = session.clone();
let session_started_at = Instant::now();
let port = tokio_serial::new(&port_name, 921600)
.open_native_async()
.map_err(|_| SerialError::OpenError)?;
let _ = tauri::async_runtime::spawn(async move {
// 这里调用新的标定处理函数
let task = tauri::async_runtime::spawn(async move {
if let Err(error) = run_serial_with_calibration(
task_app.clone(),
port,
session_started_at,
task_cancel,
session,
task_session.clone(),
)
.await
{
eprintln!("标定任务异常退出: {error}");
eprintln!("calibration task exited with error: {error}");
}
{
let manager = task_app.state::<SerialConnectionState>();
let Ok(mut runtime) = manager.calibration_runtime.lock() else {
return;
};
let should_clear = runtime
.as_ref()
.map(|current: &CalibrationRuntime| Arc::ptr_eq(&current.session, &task_session))
.unwrap_or(false);
if should_clear {
runtime.take();
}
}
});
// 保存标定会话状态
let mut calibration_session = state
.calibration_session
let mut runtime = state
.calibration_runtime
.lock()
.map_err(|_| SerialError::StateError)?;
*calibration_session = Some(session_for_state);
if runtime.is_some() {
cancel.cancel();
task.abort();
return Err(SerialError::AlreadyConnected);
}
*runtime = Some(CalibrationRuntime {
session,
cancel,
task,
});
Ok(CalibrationResponse {
success: true,
message: "标定已开始".to_string(),
message: "calibration started".to_string(),
progress: Some(progress),
})
}
#[tauri::command]
pub async fn serial_calibrate_stop(
state: State<'_, SerialConnectionState>,
) -> Result<CalibrationResponse, SerialError> {
let runtime = {
let mut runtime = state
.calibration_runtime
.lock()
.map_err(|_| SerialError::StateError)?;
runtime.take()
};
let Some(CalibrationRuntime {
session,
cancel,
task,
}) = runtime
else {
return Ok(CalibrationResponse {
success: false,
message: "no active calibration".to_string(),
progress: None,
});
};
cancel.cancel();
let _ = task.await;
let progress = snapshot_progress(&session).ok();
Ok(CalibrationResponse {
success: true,
message: "calibration stopped".to_string(),
progress,
})
}
#[tauri::command]
pub async fn serial_calibrate_add_weight(
state: State<'_, SerialConnectionState>,
) -> Result<CalibrationResponse, SerialError> {
let mut calibration_session = state
.calibration_session
let runtime = state
.calibration_runtime
.lock()
.map_err(|_| SerialError::StateError)?;
if let Some(session) = calibration_session.as_mut() {
match session.weight_added() {
Ok(_) => Ok(CalibrationResponse {
success: true,
message: "配重已添加,继续标定".to_string(),
progress: Some(session.get_progress()),
}),
Err(e) => Err(SerialError::StateError),
}
} else {
Err(SerialError::StateError)
}
let Some(runtime) = runtime.as_ref() else {
return Err(SerialError::StateError);
};
let mut session = runtime
.session
.lock()
.map_err(|_| SerialError::StateError)?;
session
.weight_added()
.map_err(|_| SerialError::StateError)?;
Ok(CalibrationResponse {
success: true,
message: "calibration advanced".to_string(),
progress: Some(session.get_progress()),
})
}
#[tauri::command]
pub fn serial_calibrate_status(
state: State<'_, SerialConnectionState>,
) -> Result<CalibrationResponse, SerialError> {
let calibration_session = state
.calibration_session
let runtime = state
.calibration_runtime
.lock()
.map_err(|_| SerialError::StateError)?;
if let Some(session) = calibration_session.as_ref() {
if let Some(runtime) = runtime.as_ref() {
let progress = snapshot_progress(&runtime.session)?;
Ok(CalibrationResponse {
success: true,
message: "标定状态".to_string(),
progress: Some(session.get_progress()),
message: "calibration active".to_string(),
progress: Some(progress),
})
} else {
Ok(CalibrationResponse {
success: false,
message: "没有活跃的标定会话".to_string(),
message: "no active calibration".to_string(),
progress: None,
})
}

View File

@@ -94,7 +94,9 @@ pub fn file_explorer_list(
Ok(FileExplorerListResponse {
current_path: current_path.display().to_string(),
parent_path: current_path.parent().map(|parent| parent.display().to_string()),
parent_path: current_path
.parent()
.map(|parent| parent.display().to_string()),
roots: collect_roots(&app),
entries,
})

View File

@@ -1,4 +1,4 @@
use crate::serial_core::calibration_session::CalibrationSession;
use crate::serial_core::calibration_session::SharedCalibrationSession;
use crate::serial_core::codecs::tactile_a::{
export_recording_csv, TactileACodec, TactileACsvImporter, TactileAHandler,
};
@@ -71,11 +71,32 @@ struct SerialSession {
current_record: SharedTactileRecording,
}
pub struct CalibrationRuntime {
pub session: SharedCalibrationSession,
pub cancel: CancellationToken,
pub task: JoinHandle<()>,
}
#[derive(Default)]
pub struct SerialConnectionState {
session: Mutex<Option<SerialSession>>,
last_record: Mutex<Option<SharedTactileRecording>>,
pub calibration_session: Mutex<Option<CalibrationSession>>,
pub calibration_runtime: Mutex<Option<CalibrationRuntime>>,
}
impl SerialConnectionState {
pub(crate) fn has_active_serial_session(&self) -> Result<bool, SerialError> {
let session = self.session.lock().map_err(|_| SerialError::StateError)?;
Ok(session.is_some())
}
pub(crate) fn has_active_calibration(&self) -> Result<bool, SerialError> {
let runtime = self
.calibration_runtime
.lock()
.map_err(|_| SerialError::StateError)?;
Ok(runtime.is_some())
}
}
#[tauri::command]
@@ -100,11 +121,8 @@ pub async fn serial_connect(
return Err(SerialError::InvalidConfig);
}
{
let session = state.session.lock().map_err(|_| SerialError::StateError)?;
if session.is_some() {
return Err(SerialError::AlreadyConnected);
}
if state.has_active_serial_session()? || state.has_active_calibration()? {
return Err(SerialError::AlreadyConnected);
}
let cancel = CancellationToken::new();

View File

@@ -26,7 +26,10 @@ pub fn win_toggle_maximize(app: AppHandle) -> Result<(), String> {
}
#[tauri::command]
pub async fn win_close(app: AppHandle, state: State<'_, SerialConnectionState>) -> Result<(), String> {
pub async fn win_close(
app: AppHandle,
state: State<'_, SerialConnectionState>,
) -> Result<(), String> {
disconnect_active_session(state.inner())
.await
.map_err(|error| error.to_string())?;