update ignore
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use crate::serial_core::frame::TactileAFrame;
|
||||
use crate::serial_core::record::{RecordedFrame, Recording};
|
||||
use crate::serial_core::record::RecordedFrame;
|
||||
use serde::Serialize;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
@@ -8,8 +8,7 @@ use std::sync::{Arc, Mutex};
|
||||
pub enum CalibrationState {
|
||||
Idle,
|
||||
CollectingData,
|
||||
ExportingData,
|
||||
WaitingForWeight,
|
||||
WaitingForNextRound,
|
||||
Completed,
|
||||
}
|
||||
|
||||
@@ -17,21 +16,23 @@ pub enum CalibrationState {
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CalibrationSession {
|
||||
pub state: CalibrationState,
|
||||
pub target_frame: usize,
|
||||
pub target_frames: usize,
|
||||
pub collected_frames: usize,
|
||||
pub current_round: usize,
|
||||
pub max_rounds: usize,
|
||||
pub round_interval_ms: u64,
|
||||
pub data: Vec<RecordedFrame<TactileAFrame>>,
|
||||
}
|
||||
|
||||
impl CalibrationSession {
|
||||
pub fn new(targt_frame: usize, max_round: usize) -> Self {
|
||||
pub fn new(target_frames: usize, max_rounds: usize, round_interval_ms: u64) -> Self {
|
||||
Self {
|
||||
state: CalibrationState::Idle,
|
||||
target_frame: targt_frame,
|
||||
target_frames,
|
||||
collected_frames: 0,
|
||||
current_round: 1,
|
||||
max_rounds: max_round,
|
||||
max_rounds,
|
||||
round_interval_ms,
|
||||
data: Vec::new(),
|
||||
}
|
||||
}
|
||||
@@ -40,10 +41,6 @@ impl CalibrationSession {
|
||||
self.state = CalibrationState::CollectingData;
|
||||
self.collected_frames = 0;
|
||||
self.data.clear();
|
||||
println!(
|
||||
"标定第 {} 轮开始,目标收集 {} 个有效帧",
|
||||
self.current_round, self.target_frame
|
||||
);
|
||||
}
|
||||
|
||||
pub fn add_frame(&mut self, frame: RecordedFrame<TactileAFrame>) -> bool {
|
||||
@@ -53,24 +50,24 @@ impl CalibrationSession {
|
||||
|
||||
self.data.push(frame);
|
||||
self.collected_frames += 1;
|
||||
|
||||
if self.collected_frames >= self.target_frame {
|
||||
self.state = CalibrationState::ExportingData;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
self.collected_frames >= self.target_frames
|
||||
}
|
||||
|
||||
pub fn export_completed(&mut self) {
|
||||
self.state = CalibrationState::WaitingForWeight;
|
||||
println!("请修改配重,继续标定");
|
||||
if self.current_round >= self.max_rounds {
|
||||
self.state = CalibrationState::Completed;
|
||||
} else {
|
||||
self.state = CalibrationState::WaitingForNextRound;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn weight_added(&mut self) -> Result<(), String> {
|
||||
self.begin_next_round()
|
||||
}
|
||||
|
||||
pub fn begin_next_round(&mut self) -> Result<(), String> {
|
||||
if self.current_round >= self.max_rounds {
|
||||
self.state = CalibrationState::Completed;
|
||||
println!("标定完成,共 {} 轮", self.current_round);
|
||||
} else {
|
||||
self.current_round += 1;
|
||||
self.start();
|
||||
@@ -79,15 +76,30 @@ impl CalibrationSession {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn stop(&mut self) {
|
||||
self.state = CalibrationState::Idle;
|
||||
self.collected_frames = 0;
|
||||
self.data.clear();
|
||||
}
|
||||
|
||||
pub fn is_active(&self) -> bool {
|
||||
matches!(
|
||||
self.state,
|
||||
CalibrationState::CollectingData | CalibrationState::WaitingForNextRound
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_progress(&self) -> CalibrationProgress {
|
||||
CalibrationProgress {
|
||||
state: self.state.clone(),
|
||||
current_round: self.current_round,
|
||||
max_rounds: self.max_rounds,
|
||||
collected_frames: self.collected_frames,
|
||||
target_frames: self.target_frame,
|
||||
progress_percentage: if self.target_frame > 0 {
|
||||
(self.collected_frames as f32 / self.target_frame as f32) * 100.0
|
||||
target_frames: self.target_frames,
|
||||
round_interval_ms: self.round_interval_ms,
|
||||
is_active: self.is_active(),
|
||||
progress_percentage: if self.target_frames > 0 {
|
||||
(self.collected_frames as f32 / self.target_frames as f32) * 100.0
|
||||
} else {
|
||||
0.0
|
||||
},
|
||||
@@ -103,7 +115,9 @@ pub struct CalibrationProgress {
|
||||
pub max_rounds: usize,
|
||||
pub collected_frames: usize,
|
||||
pub target_frames: usize,
|
||||
pub round_interval_ms: u64,
|
||||
pub is_active: bool,
|
||||
pub progress_percentage: f32,
|
||||
}
|
||||
|
||||
pub type SharedCalibrationSession = Arc<Mutex<Option<CalibrationSession>>>;
|
||||
pub type SharedCalibrationSession = Arc<Mutex<CalibrationSession>>;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::serial_core::{frame::TestFrame, record::Recording};
|
||||
|
||||
|
||||
pub mod tactile_a;
|
||||
pub mod test;
|
||||
pub type TestRecording = Recording<TestFrame>;
|
||||
|
||||
@@ -13,14 +13,12 @@ use async_trait::async_trait;
|
||||
use csv::StringRecord;
|
||||
use log::debug;
|
||||
use std::io::Read;
|
||||
use std::os::raw;
|
||||
|
||||
const FRAME_BUFFER_MIN_LENGTH: usize = 15;
|
||||
const IGNOR_RAW_DATA_VAL: i32 = 10;
|
||||
|
||||
pub struct TactileACodec {
|
||||
buffer: Vec<u8>,
|
||||
frame_nb: u64,
|
||||
expected_data_len: usize,
|
||||
}
|
||||
|
||||
@@ -68,7 +66,6 @@ impl TactileACodec {
|
||||
pub fn new(cols: usize, rows: usize) -> TactileACodec {
|
||||
Self {
|
||||
buffer: Vec::new(),
|
||||
frame_nb: 0,
|
||||
expected_data_len: cols * rows * 2,
|
||||
}
|
||||
}
|
||||
@@ -82,7 +79,6 @@ impl TactileACodec {
|
||||
.chunks_exact(2)
|
||||
.map(|chunk| {
|
||||
let mut raw_val = u16::from_le_bytes([chunk[0], chunk[1]]) as i32;
|
||||
println!("raw_val: {}", raw_val);
|
||||
if raw_val < IGNOR_RAW_DATA_VAL {
|
||||
raw_val = 0;
|
||||
}
|
||||
@@ -245,7 +241,7 @@ impl FrameHandler<TactileAFrame, i32> for TactileAHandler {
|
||||
match frame {
|
||||
TactileAFrame::Rep(rep) => {
|
||||
let vals = TactileACodec::parse_data_frame(&rep.payload)?;
|
||||
debug!("vals is {:?}", vals);
|
||||
|
||||
Ok(Some(vals))
|
||||
}
|
||||
_ => Ok(None),
|
||||
@@ -253,6 +249,15 @@ impl FrameHandler<TactileAFrame, i32> for TactileAHandler {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn trans_data_2_n(val: i32) -> i32 {
|
||||
if val <= 74602 {
|
||||
val / 466
|
||||
} else if val > 74602 && val <= 105503 {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
impl TactileACsvExporter {
|
||||
pub fn new(channels: usize) -> Self {
|
||||
TactileACsvExporter {
|
||||
@@ -271,7 +276,7 @@ impl TactileACsvExporter {
|
||||
|
||||
impl CsvExporter<TactileARepFrame> for TactileACsvExporter {
|
||||
type Error = CodecError;
|
||||
fn csv_header(&self, recording: &Recording<TactileARepFrame>) -> Vec<String> {
|
||||
fn csv_header(&self, _recording: &Recording<TactileARepFrame>) -> Vec<String> {
|
||||
let mut header: Vec<String> = Vec::new();
|
||||
for i in 0..self.channels {
|
||||
header.push(format!("channel{}", i + 1));
|
||||
|
||||
@@ -244,9 +244,7 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use csv::Reader;
|
||||
use std::io::Cursor;
|
||||
|
||||
#[test]
|
||||
fn test_read_csv_basic() -> anyhow::Result<()> {
|
||||
|
||||
@@ -37,7 +37,7 @@ impl<F> Recording<F> {
|
||||
pub fn push(&mut self, ite: RecordedFrame<F>) {
|
||||
self.frames.push(ite);
|
||||
}
|
||||
pub fn check_frame_need_record(ite: RecordedFrame<F>) {}
|
||||
pub fn check_frame_need_record(_ite: RecordedFrame<F>) {}
|
||||
}
|
||||
|
||||
pub trait CsvExporter<F> {
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
use std::time::Instant;
|
||||
|
||||
pub fn usize_to_u16_be_bytes(n: usize) -> [u8; 2] {
|
||||
@@ -41,7 +40,9 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_crc8_itu() -> anyhow::Result<()> {
|
||||
let req_vec = vec![0x55, 0xAA, 0x09, 0x00, 0x34, 0x00, 0xFB, 0x00, 0x1C, 0x00, 0x00, 0x18, 0x00];
|
||||
let req_vec = vec![
|
||||
0x55, 0xAA, 0x09, 0x00, 0x34, 0x00, 0xFB, 0x00, 0x1C, 0x00, 0x00, 0x18, 0x00,
|
||||
];
|
||||
let checksum = calc_crc8_itu(req_vec.as_slice());
|
||||
assert_eq!(checksum, 0x7A);
|
||||
|
||||
@@ -50,10 +51,12 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_crc8_smbus() -> anyhow::Result<()> {
|
||||
let req_vec = vec![0x55, 0xAA, 0x09, 0x00, 0x34, 0x00, 0xFB, 0x00, 0x1C, 0x00, 0x00, 0x18, 0x00];
|
||||
let req_vec = vec![
|
||||
0x55, 0xAA, 0x09, 0x00, 0x34, 0x00, 0xFB, 0x00, 0x1C, 0x00, 0x00, 0x18, 0x00,
|
||||
];
|
||||
let checksum = calc_crc8_smbus(req_vec.as_slice());
|
||||
assert_eq!(checksum, 0x2F);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user