baoshiwei
5 天以前 2ad852ee08e21ee681950f1d6058499248baf88e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
use std::io::{Write, ErrorKind};
use tauri::Emitter;
use std::time::Duration;
use serialport::{self, SerialPort};
 
use once_cell::sync::Lazy;
use tokio::sync::{Mutex, broadcast};
 
 
// 用于发送停止信号的通道
static STOP_SIGNAL_SENDER: Lazy<Mutex<Option<broadcast::Sender<()>>>> = Lazy::new(|| Mutex::new(None));
 
// 使用Lazy和Mutex来安全地共享串口实例
static SERIAL_PORT: Lazy<Mutex<Option<Box<dyn SerialPort>>>> = Lazy::new(|| Mutex::new(None));
 
#[tauri::command]
pub async fn open_serial_port(app_handle: tauri::AppHandle, port_name: String, baud_rate: u32) -> Result<String, String> {
    // 输出 串口名称
    println!("打开串口: {}", port_name);
    // 输出 波特率
    println!("波特率: {}", baud_rate);
    let mut serial_port_guard = SERIAL_PORT.lock().await;
    if serial_port_guard.is_some() {
        return Err("串口已打开".into());
    }
 
    match serialport::new(&port_name, baud_rate)
        .timeout(Duration::from_millis(10))
        .open()
    {
        Ok(port) => {
            *serial_port_guard = Some(port);
 
            // 创建停止信号通道
            let (tx, _rx) = broadcast::channel(1);
            *STOP_SIGNAL_SENDER.lock().await = Some(tx.clone());
 
            let app_handle_clone = app_handle.clone();
            let mut rx_stop = tx.subscribe();
 
            tokio::spawn(async move {
                let mut buffer: Vec<u8> = vec![0; 1024];
                let mut data_buffer: Vec<u8> = Vec::new(); // Buffer to accumulate incoming data
                loop {
                    tokio::select! {
                        _ = rx_stop.recv() => {
                            println!("停止串口数据读取任务");
                            break;
                        }
                        _ = tokio::time::sleep(Duration::from_millis(100)) => {
                            // 定期尝试读取,避免长时间阻塞
                            let mut serial_port_guard = SERIAL_PORT.lock().await;
                            if let Some(port) = serial_port_guard.as_mut() {
                                match port.read(buffer.as_mut_slice()) {
                                    Ok(bytes_read) => {
                                        if bytes_read > 0 {
                                            data_buffer.extend_from_slice(&buffer[..bytes_read]);
 
                                            // Process data_buffer to extract complete 22-byte packets
                                            while data_buffer.len() >= 22 {
                                                let data = data_buffer.drain(..22).collect::<Vec<u8>>();
                                                if let Err(e) = app_handle_clone.emit("serial_data", data) {
                                                    eprintln!("发射事件失败: {}", e);
                                                }
                                            }
                                        }
                                    }
                                    Err(ref e) if e.kind() == ErrorKind::TimedOut => { /* 超时,继续 */ }
                                    Err(e) => {
                                        eprintln!("读取串口数据失败: {}", e);
                                        break; // 读取失败,退出循环
                                    }
                                }
                            } else {
                                eprintln!("串口未打开,停止读取任务");
                                break;
                            }
                        }
                    }
                }
            });
            let log_message = format!("成功打开串口: {}", port_name);
            crate::log_data(app_handle, log_message.clone()).map_err(|e| e.to_string())?;
            Ok(log_message)
        }
        Err(e) => Err(format!("打开串口失败: {}", e)),
    }
}
 
#[tauri::command]
pub async fn close_serial_port() -> Result<String, String> {
    let mut serial_port_guard = SERIAL_PORT.lock().await;
    if serial_port_guard.is_none() {
        return Err("串口未打开".into());
    }
 
    // 发送停止信号
    if let Some(tx) = STOP_SIGNAL_SENDER.lock().await.take() {
        if let Err(e) = tx.send(()) {
            eprintln!("发送停止信号失败: {}", e);
        }
    }
 
    *serial_port_guard = None;
    Ok("串口已关闭".into())
}
 
// 移除 read_serial_data 命令,因为读取逻辑已集成到 open_serial_port 中
// #[tauri::command]
// pub async fn read_serial_data(app_handle: tauri::AppHandle) -> Result<Vec<u8>, String> {
//     let mut serial_port_guard = SERIAL_PORT.lock().await;
//     if let Some(port) = serial_port_guard.as_mut() {
//         let mut buffer: Vec<u8> = vec![0; 128]; // 假设每次最多读取128字节
//         match port.read(buffer.as_mut_slice()) {
//             Ok(bytes_read) => {
//                 let data = buffer[..bytes_read].to_vec();
//                 // 可以在这里发射事件到前端,如果需要实时显示
//                 // app_handle.emit_all("serial_data", &data).unwrap();
//                 Ok(data)
//             }
//             Err(ref e) if e.kind() == ErrorKind::TimedOut => Ok(vec![]), // 超时不是错误
//             Err(e) => Err(format!("读取串口数据失败: {}", e)),
//         }
//     } else {
//         Err("串口未打开".into())
//     }
// }
 
#[tauri::command]
pub async fn write_serial_data(data: Vec<u8>) -> Result<usize, String> {
    let mut serial_port_guard = SERIAL_PORT.lock().await;
    if let Some(port) = serial_port_guard.as_mut() {
        match port.write_all(&data) {
            Ok(_) => Ok(data.len()),
            Err(e) => Err(format!("写入串口数据失败: {}", e)),
        }
    } else {
        Err("串口未打开".into())
    }
}
 
#[tauri::command]
pub fn list_serial_ports() -> Result<Vec<String>, String> {
    match serialport::available_ports() {
        Ok(ports) => {
            let port_names = ports.into_iter().map(|p| p.port_name).collect();
            Ok(port_names)
        }
        Err(e) => Err(format!("列出串口失败: {}", e)),
    }
}