Added features:
1. use two files in this project
2. use thread to read and send messages
Fixed issues:
1. need set timeout for receive serial port, or it won't wait for the data and just return.
vserial.rs
use serialport::{SerialPort, SerialPortSettings};
// Define a trait for the serial port operations
pub trait SerialOperations {
fn open(&mut self) -> Result<(), std::io::Error>;
fn write(&mut self, data: &[u8]) -> Result<(), std::io::Error>;
fn receive(&mut self, buffer: &mut [u8]) -> Result;
}
// Implement the SerialOperations trait for the Comm struct
pub struct Comm {
pub port_name: String,
pub port: Option>,
}
impl SerialOperations for Comm {
fn open(&mut self) -> Result<(), std::io::Error> {
// Create the serial port settings
let settings = SerialPortSettings {
baud_rate: 9600,
..Default::default()
};
// Try to open the serial port with the specified settings
match serialport::open_with_settings(&self.port_name, &settings) {
Ok(p) => {
self.port = Some(p);
Ok(())
},
Err(e) => {
println!("Error opening serial port: {}", e);
Err(e.into())
}
}
}
fn write(&mut self, data: &[u8]) -> Result<(), std::io::Error> {
if let Some(port) = &mut self.port {
port.write(data)?;
Ok(())
} else {
Err(std::io::Error::new(
std::io::ErrorKind::Other,
"Serial port not open",
))
}
}
fn receive(&mut self, buffer: &mut [u8]) -> Result {
if let Some(port) = &mut self.port {
//Ok(port.read(buffer)?)
match port.read(buffer) {
Ok(bytes_read) => Ok(bytes_read),
Err(e) => {
println!("Error reading from serial port: {}", e);
Err(e.into())
}
}
} else {
Err(std::io::Error::new(
std::io::ErrorKind::Other,
"Serial port not open",
))
}
}
}
pub fn mod_test(){
println!("this is module function call\n")
}
main.rs
mod vserial;
use crate::vserial::{Comm,SerialOperations};
use std::thread;
use std::time::Duration;
fn thread_send(name: &str)
{
let mut count = 0;
let mut comm_send = Comm {
port_name: "/dev/ttyVSP0".to_string(),
port: None,
};
println!("Thread {} started\n",name);
// Open the serial port
match comm_send.open() {
Ok(p) => p,
Err(e) => {
println!("Error opening serial port: {}", e);
return;
}
};
loop {
// Write data to the serial port
if let Err(e) = comm_send.write(b"Hello World!\n") {
println!("Error writing to serial port: {}", e);
return;
}
if count == 10 { break;}
count += 1;
}
println!("Thread {} end\n",name);
}
fn thread_recv(name: &str)
{
let mut comm_recv = Comm {
port_name: "/dev/ttyVSP4".to_string(),
port: None,
};
println!("Thread {} started\n",name);
// Open the serial port
match comm_recv.open() {
Ok(p) => p,
Err(e) => {
println!("Error opening serial port: {}", e);
return;
}
};
let _ = match comm_recv.port.as_mut() {
Some(port) => { /*expected port of Comm*/
let mut comm_timeout = port.timeout(); /*directly use port of Comm*/
println!("Duration is seconds: {:.2?}\n",comm_timeout.as_secs_f32());
comm_timeout = Duration::from_secs(1);
let _ = port.set_timeout(comm_timeout);
},
None => {
// Handle the absence of a port here
()
}
};
/*let mut comm_port = comm_recv.port.as_mut();
let mut comm_timeout = comm_port.as_mut().unwrap().timeout();
println!("Duration is seconds: {:.2?}\n",comm_timeout.as_secs_f32());
comm_timeout = Duration::from_secs(1);
let _ = comm_port.as_mut().unwrap().set_timeout(comm_timeout);*/
loop {
// Receive data from the serial port
let mut buffer = [0; 256];
if let Err(e) = comm_recv.receive(&mut buffer) {
println!("Error receiving from serial port: {}", e);
break;
}
match std::str::from_utf8(&buffer) {
Ok(s) => println!("{}", s),
Err(_) => println!("Invalid UTF-8 sequence"),
}
}
println!("Thread {} end\n",name);
}
fn main() {
vserial::mod_test();
thread::spawn(||{
thread_recv("thread_recv");
});
thread::spawn(||{
thread_send("thread_send");
});
thread::sleep(Duration::from_secs(10));
}
Cargo.toml
[package]
name = "vserial"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serialport = "3.1"
[lib]
path = "src/vserial.rs"