147 lines
4.0 KiB
Rust
147 lines
4.0 KiB
Rust
use std::sync::mpsc::{Sender, Receiver};
|
|
use std::env;
|
|
use serialport::{SerialPort, DataBits, Parity, FlowControl, StopBits};
|
|
use std::time::Duration;
|
|
|
|
|
|
pub enum Message {
|
|
UiUpdateLog(String),
|
|
UiUpdateReceiveMsg(Vec<u8>),
|
|
UiCleanReceiveMsg,
|
|
UiCleanLog,
|
|
UiShowLog,
|
|
UiHideLog,
|
|
UiShowHex,
|
|
UiHideHex,
|
|
|
|
UiUpdateStatusBarCom(String),
|
|
UiUpdateStatusBarBaudrate(u32),
|
|
UiUpdateStatusBarParity(String),
|
|
UiUpdateStatusBarStopbit(u32),
|
|
UiUpdateStatusBarPeriod(u64),
|
|
UiUpdateStatusBarDatabit(u32),
|
|
|
|
MainCmdOpen(String),
|
|
MainCmdClose,
|
|
MainCmdSend(String),
|
|
MainCmdSet(Vec<String>),
|
|
MainCmdSendPeriod(String),
|
|
MainCmdStopPeriod,
|
|
|
|
PortCmdClose,
|
|
PortCmdSend(String),
|
|
|
|
PortPeriodSend(String),
|
|
PortPeriodStop,
|
|
PortPeriodDuration(u64),
|
|
|
|
PortCloseSucceed,
|
|
PortHaveData(Vec<u8>),
|
|
PortError(String),
|
|
}
|
|
|
|
pub enum Error {
|
|
PortOpenFailed(String),
|
|
}
|
|
|
|
#[derive(Copy, Clone)]
|
|
pub struct PortConfig {
|
|
pub baud_rate: u32,
|
|
pub data_bits: DataBits,
|
|
pub parity: Parity,
|
|
pub flow_control: FlowControl,
|
|
pub stopbit: StopBits,
|
|
pub timeout: u32,
|
|
}
|
|
|
|
pub fn port_open(port: String, config: PortConfig) -> Result<Box<dyn SerialPort>, Error> {
|
|
let mut prelude = "";
|
|
if env::consts::OS == "linux" { prelude = "/dev/tty"; } else if env::consts::OS == "windows" { prelude = "" }
|
|
let port_builder = serialport::new(prelude.to_owned() + &port, config.baud_rate)
|
|
.data_bits(config.data_bits)
|
|
.parity(config.parity)
|
|
.flow_control(config.flow_control)
|
|
.stop_bits(config.stopbit)
|
|
.timeout(Duration::from_millis(config.timeout as u64));
|
|
match port_builder.open() {
|
|
Ok(port) => { return Ok(port); }
|
|
Err(e) => {
|
|
let err_msg = format!("Open port failed with error {}\n", e).to_string();
|
|
return Err(Error::PortOpenFailed(err_msg));
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn port_proc(mut port: Box<dyn SerialPort>, to_main: Sender<Message>, from_main: Receiver<Message>) {
|
|
let mut buf: Vec<u8> = vec![0; 128];
|
|
let mut period_send = false;
|
|
let mut period_timeout = std::time::Duration::from_millis(100);
|
|
let mut period_send_msg = String::new();
|
|
let mut last_send = std::time::Instant::now();
|
|
to_main.send(Message::PortPeriodDuration(100));
|
|
loop {
|
|
if let Ok(msg) = from_main.try_recv() {
|
|
match msg {
|
|
Message::PortCmdClose => {
|
|
to_main.send(Message::PortCloseSucceed).unwrap();
|
|
break;
|
|
}
|
|
Message::PortCmdSend(msg) => {
|
|
match port.write(msg.as_bytes()) {
|
|
Err(e) => {
|
|
to_main.send(Message::PortError(format!("{}", e).to_string())).unwrap();
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
Message::PortPeriodSend(msg) => {
|
|
period_send = true;
|
|
period_send_msg = msg;
|
|
}
|
|
Message::PortPeriodStop=> {
|
|
period_send = false;
|
|
}
|
|
Message::PortPeriodDuration(value) => {
|
|
period_timeout = std::time::Duration::from_millis(value);
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
match port.read(buf.as_mut_slice()) {
|
|
Ok(size) => to_main.send(Message::PortHaveData(buf[0..size].to_owned())).unwrap(),
|
|
Err(e) => {
|
|
if e.kind() != std::io::ErrorKind::TimedOut {
|
|
to_main.send(Message::PortError(format!("{}", e).to_string())).unwrap();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if period_send && (last_send.elapsed() > period_timeout){
|
|
last_send = std::time::Instant::now();
|
|
match port.write(period_send_msg.as_bytes()) {
|
|
Err(e) => to_main.send(Message::PortError(format!("{}", e).to_string())).unwrap(),
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub(crate) fn list_available_ports() -> (String, String) {
|
|
let mut ret = String::new();
|
|
let mut ret_portname = String::new();
|
|
match serialport::available_ports() {
|
|
Ok(ports) => {
|
|
for p in ports {
|
|
ret += &*String::from(format!("{:?}\n", p));
|
|
if ret_portname.is_empty() {
|
|
ret_portname = p.port_name;
|
|
}
|
|
}
|
|
}
|
|
Err(err) => {
|
|
ret = format!("{}", err);
|
|
}
|
|
}
|
|
(ret, ret_portname)
|
|
}
|