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,4 +1,4 @@
use crate::serial_core::calibration_session::*;
use crate::serial_core::calibration_session::*;
use crate::serial_core::codec::Codec;
use crate::serial_core::codecs::tactile_a::TactileACodec;
use crate::serial_core::frame::{FrameHandler, TactileAFrame, TestFrame};
@@ -164,9 +164,9 @@ impl PollRequester<TactileAFrame> for TactileAPollRequester {
pub async fn run_serial<C, H, T, F>(
app: AppHandle,
mut port: SerialStream,
mut codec: C,
mut handler: H,
port: SerialStream,
codec: C,
handler: H,
session_started_at: Instant,
recording: Arc<Mutex<Recording<F>>>,
cancel: CancellationToken,
@@ -294,111 +294,218 @@ where
Ok(())
}
// src-tauri/src/serial_core/serial.rs 中添加
// 鍦?src-tauri/src/serial_core/serial.rs 涓坊鍔?
pub async fn run_serial_with_calibration(
app: AppHandle,
mut port: SerialStream,
session_started_at: Instant,
cancel: CancellationToken,
mut calibration_session: CalibrationSession,
calibration_session: SharedCalibrationSession,
) -> Result<()> {
let mut codec = TactileACodec::new(DEFAULT_TACTILE_COLS, DEFAULT_TACTILE_ROWS);
let mut handler = TactileAHandler;
let mut requester = TactileAPollRequester::new(
Duration::from_millis(DEFAULT_TACTILE_POLL_INTERVAL_MS),
DEFAULT_TACTILE_COLS,
DEFAULT_TACTILE_ROWS,
Duration::from_millis(DEFAULT_TACTILE_REPLY_TIMEOUT_MS),
);
info!("run_serial_with_calibration begin");
emit_calibration_status(&app, &calibration_session)?;
let mut poll_interval = time::interval(Duration::from_millis(DEFAULT_TACTILE_POLL_INTERVAL_MS));
poll_interval.set_missed_tick_behavior(MissedTickBehavior::Skip);
let run_result = async {
let mut codec = TactileACodec::new(DEFAULT_TACTILE_COLS, DEFAULT_TACTILE_ROWS);
let mut handler = TactileAHandler;
let mut requester = TactileAPollRequester::new(
Duration::from_millis(DEFAULT_TACTILE_POLL_INTERVAL_MS),
DEFAULT_TACTILE_COLS,
DEFAULT_TACTILE_ROWS,
Duration::from_millis(DEFAULT_TACTILE_REPLY_TIMEOUT_MS),
);
let mut buffer = [0u8; 1024];
let recording = Arc::new(Mutex::new(Recording::new()));
let mut chart_state = HudChartState::new();
let mut prune_interval = time::interval(Duration::from_millis(450));
prune_interval.set_missed_tick_behavior(MissedTickBehavior::Delay);
let mut poll_interval =
time::interval(Duration::from_millis(DEFAULT_TACTILE_POLL_INTERVAL_MS));
poll_interval.set_missed_tick_behavior(MissedTickBehavior::Skip);
loop {
tokio::select! {
_ = cancel.cancelled() => break,
_ = poll_interval.tick() => {
if requester.should_request() {
if let Some(req) = requester.next_request()? {
let bytes = codec.encode(&req)?;
port.write_all(&bytes).await?;
let mut buffer = [0u8; 1024];
let recording = Arc::new(Mutex::new(Recording::new()));
let mut chart_state = HudChartState::new();
let mut prune_interval = time::interval(Duration::from_millis(450));
prune_interval.set_missed_tick_behavior(MissedTickBehavior::Delay);
let mut next_round_at: Option<Instant> = None;
loop {
tokio::select! {
_ = cancel.cancelled() => break,
_ = poll_interval.tick() => {
if let Some(deadline) = next_round_at {
if Instant::now() >= deadline {
next_round_at = None;
begin_next_calibration_round(&app, &calibration_session)?;
}
}
}
}
_ = prune_interval.tick() => {
if let Some(packet) = chart_state.prune_stale() {
app.emit("hud_stream", packet)?;
}
}
read_result = port.read(&mut buffer) => {
let n = read_result?;
if n == 0 {
tokio::task::yield_now().await;
continue;
}
let frames = codec.decode(&buffer[..n], session_started_at)?;
for frame in frames {
requester.on_rx_frame(&frame);
let decode_res = handler
.on_frame(&frame)
.await?
.map(|vals| vals.into_iter().map(Into::into).collect::<Vec<i32>>());
let recorded_frame = RecordedFrame {
timing: FrameTiming { pts_ms: None, dts_ms: frame.dts_ms() },
frame: frame.clone(),
};
if calibration_is_collecting(&calibration_session)?
&& requester.should_request()
{
let mut record = recording
.lock()
.map_err(|_| anyhow::anyhow!("recording state poisoned"))?;
record.push(recorded_frame.clone());
if let Some(req) = requester.next_request()? {
let bytes = codec.encode(&req)?;
port.write_all(&bytes).await?;
}
}
let display_values = if let Some(vals) = decode_res.as_ref() {
let summary = vals.iter().copied().sum::<i32>();
chart_state.record_summary(summary as f32);
chart_state.record_pressure_matrix(vals.as_slice());
Some(vec![summary])
} else {
None
};
if let Some(packet) = frame.to_hud_packet(&mut chart_state, display_values.as_deref()) {
}
_ = prune_interval.tick() => {
if let Some(packet) = chart_state.prune_stale() {
app.emit("hud_stream", packet)?;
}
}
read_result = port.read(&mut buffer) => {
let n = read_result?;
if n == 0 {
tokio::task::yield_now().await;
continue;
}
// 检查是否达到目标帧数
let should_export = calibration_session.add_frame(recorded_frame);
let frames = codec.decode(&buffer[..n], session_started_at)?;
for frame in frames {
requester.on_rx_frame(&frame);
if should_export {
// 导出数据
export_calibration_data(&app, &calibration_session, &recording).await?;
let decode_res = handler
.on_frame(&frame)
.await?
.map(|vals| vals.into_iter().map(Into::into).collect::<Vec<i32>>());
// 发送语音提示(这里用事件代替,前端可以播放语音)
app.emit("calibration_voice_prompt", "请添加配重")?;
let display_values = if let Some(vals) = decode_res.as_ref() {
let summary = vals.iter().copied().sum::<i32>();
let val_summary = summary - vals[vals.len() - 1];
if val_summary < 8400 {
continue;
}
chart_state.record_summary(summary as f32);
chart_state.record_pressure_matrix(vals.as_slice());
Some(vec![summary])
} else {
None
};
// 更新状态
calibration_session.export_completed();
let recorded_frame = RecordedFrame {
timing: FrameTiming { pts_ms: None, dts_ms: frame.dts_ms() },
frame: frame.clone(),
};
if let Ok(mut record) = recording.lock() {
record.frames.clear();
{
let mut record = recording
.lock()
.map_err(|_| anyhow::anyhow!("recording state poisoned"))?;
record.push(recorded_frame.clone());
}
if let Some(packet) = frame.to_hud_packet(&mut chart_state, display_values.as_deref()) {
app.emit("hud_stream", packet)?;
}
let should_export = {
let mut session = calibration_session
.lock()
.map_err(|_| anyhow::anyhow!("calibration session poisoned"))?;
session.add_frame(recorded_frame)
};
if should_export {
let current_round = {
let session = calibration_session
.lock()
.map_err(|_| anyhow::anyhow!("calibration session poisoned"))?;
session.current_round
};
export_calibration_data(&app, current_round, &recording).await?;
let (progress, round_interval_ms) = {
let mut session = calibration_session
.lock()
.map_err(|_| anyhow::anyhow!("calibration session poisoned"))?;
session.export_completed();
(session.get_progress(), session.round_interval_ms)
};
app.emit("calibration_status", progress.clone())?;
if let Ok(mut record) = recording.lock() {
record.frames.clear();
}
if progress.state == CalibrationState::Completed {
return Ok(());
}
if round_interval_ms == 0 {
begin_next_calibration_round(&app, &calibration_session)?;
} else {
next_round_at =
Some(Instant::now() + Duration::from_millis(round_interval_ms));
}
}
}
}
}
}
Ok(())
}
.await;
if cancel.is_cancelled() {
stop_calibration_session(&app, &calibration_session)?;
}
run_result
}
fn calibration_is_collecting(calibration_session: &SharedCalibrationSession) -> Result<bool> {
let session = calibration_session
.lock()
.map_err(|_| anyhow::anyhow!("calibration session poisoned"))?;
Ok(session.state == CalibrationState::CollectingData)
}
fn begin_next_calibration_round(
app: &AppHandle,
calibration_session: &SharedCalibrationSession,
) -> Result<()> {
{
let mut session = calibration_session
.lock()
.map_err(|_| anyhow::anyhow!("calibration session poisoned"))?;
if session.state == CalibrationState::WaitingForNextRound {
session
.begin_next_round()
.map_err(|error| anyhow::anyhow!(error))?;
}
}
emit_calibration_status(app, calibration_session)
}
fn stop_calibration_session(
app: &AppHandle,
calibration_session: &SharedCalibrationSession,
) -> Result<()> {
{
let mut session = calibration_session
.lock()
.map_err(|_| anyhow::anyhow!("calibration session poisoned"))?;
if session.state != CalibrationState::Completed {
session.stop();
}
}
emit_calibration_status(app, calibration_session)
}
fn emit_calibration_status(
app: &AppHandle,
calibration_session: &SharedCalibrationSession,
) -> Result<()> {
let progress = {
let session = calibration_session
.lock()
.map_err(|_| anyhow::anyhow!("calibration session poisoned"))?;
session.get_progress()
};
app.emit("calibration_status", progress)?;
Ok(())
}
use crate::serial_core::codecs::tactile_a::TactileACsvExporter;
@@ -407,7 +514,7 @@ use std::time::{SystemTime, UNIX_EPOCH};
use tauri::Manager;
async fn export_calibration_data(
app: &AppHandle,
calibration_session: &CalibrationSession,
current_round: usize,
recording: &Arc<Mutex<Recording<TactileAFrame>>>,
) -> Result<()> {
let timestamp = SystemTime::now()
@@ -415,12 +522,8 @@ async fn export_calibration_data(
.map(|duration| duration.as_millis())
.unwrap_or_default();
let filename = format!(
"calibration_round{}_{}.csv",
calibration_session.current_round, timestamp
);
let filename = format!("calibration_round{}_{}.csv", current_round, timestamp);
// 创建导出目录
let mut output_dir = match app.path().desktop_dir() {
Ok(path) => path,
Err(_) => std::env::current_dir()?,
@@ -431,7 +534,6 @@ async fn export_calibration_data(
let output_path = output_dir.join(&filename);
let file = File::create(&output_path)?;
// 使用现有的导出逻辑
let recording_lock = recording
.lock()
.map_err(|_| anyhow::anyhow!("Recording poisoned"))?;
@@ -442,6 +544,5 @@ async fn export_calibration_data(
write_csv(&recording_lock, &exporter, file)?;
info!("标定数据已导出到: {}", output_path.display());
Ok(())
}