diff --git a/src/main.rs b/src/main.rs index 8a627ae..7852eb9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,8 @@ use rustyline::Editor; use rustyline::error::ReadlineError; use std::fs::OpenOptions; use std::io::{BufReader, BufRead}; +use std::net::{TcpListener, TcpStream}; +use std::collections::HashMap; pub mod perf { use chrono::{DateTime, Duration, Utc, Local}; @@ -16,6 +18,7 @@ pub mod perf { end: DateTime, delta_ms: i64, delta_mks: i64, + delta_ns: i64, } impl Perf { @@ -25,6 +28,7 @@ pub mod perf { end: Utc::now(), delta_ms: 0, delta_mks: 0, + delta_ns: 0, } } @@ -37,9 +41,11 @@ pub mod perf { self.end = Utc::now(); self.delta_ms = (self.end - self.start).num_microseconds().unwrap()/1000; self.delta_mks = (self.end - self.start).num_microseconds().unwrap(); + self.delta_ns = (self.end - self.start).num_nanoseconds().unwrap(); - if (measure == "ms") { println!("{} (ms): {:?}", out_msg, self.delta_ms); } - else { println!("{} (mks): {:?}", out_msg, self.delta_mks); } + if (measure == "mks") { println!("{} (mks): {:?}", out_msg, self.delta_mks); } + else if (measure == "ns") { println!("{} (ns): {:?}", out_msg, self.delta_ns); } + else { println!("{} (ms): {:?}", out_msg, self.delta_ms); } } pub fn stop_restart(&mut self, out_msg: &str, measure: &str) { @@ -56,6 +62,285 @@ pub mod perf { } } +use crate::perf::Perf; + +fn tcp_server() { + let listener = TcpListener::bind("127.0.0.1:10000").unwrap(); + println!("TCP-server is running"); + + for stream in listener.incoming() { + match stream { + Ok(stream) => { + println!("connect to client: {:?}", stream); + handle_client(stream); + + }, + Err(ref msg) => { + println!("error: failed attempt to set connection with client: ({:?}): {}", + stream, msg); + } + } + } +} + +fn handle_client(mut stream: TcpStream) { + let mut cmd_descr: HashMap::<&str, &str> = HashMap::new(); + cmd_descr.insert("send", "send data to serial port"); + cmd_descr.insert("exit", "cancel connection with server"); + + loop { + let mut reader = BufReader::new(&stream); + let mut rx_data = String::new(); + if let Err(msg) = reader.read_line(&mut rx_data) { + println!("error: failed attempt to read data from client: {}", msg); + return; + } + + if rx_data.contains("exit") { + println!("The client requested to close the connection"); + return; + } + } +} + + +pub mod uartTransact { + const MAX_BUF: usize = 4096; + use serialport::{SerialPort, StopBits, Parity, FlowControl, DataBits}; + use std::time::Duration; + use crate::perf::Perf; + use std::io::{self, Read, Write, BufWriter, BufReader, BufRead}; + use std::fs::{File, OpenOptions}; + use std::path::Path; + + #[derive(PartialEq)] + pub enum Type_en { + rx = 0, + tx, + rx_tx, + tx_rx, + } + + #[derive(Clone)] + pub struct PortSettings_t { + baud_rate: u32, + data_bits: DataBits, + parity: Parity, + stop_bits: StopBits, + flow_ctrl: FlowControl, + timeout_msec: u64, + } + + impl PortSettings_t { + pub fn new(baud_rate: u32, data_bits_: u8, parity_: &str, stop_bits_: u8, + flow_ctrl_: &str, timeout_msec: u64) -> Result { + + let data_bits = match data_bits_ { + 5 => DataBits::Five, + 6 => DataBits::Six, + 7 => DataBits::Seven, + 8 => DataBits::Eight, + _ => { return Err(format!( + "error: the number of data bits specified is incorrect + (type from 5 to 8)")); + } + }; + + let parity = match parity_ { + "Even" => Parity::Even, + "Odd" => Parity::Odd, + "None" => Parity::None, + _ => { return Err(format!( + "error: the parity of data specified is incorrect + (type \"Even\", \"Odd\" or \"None\")")); + } + }; + + let stop_bits = match stop_bits_ { + 1 => StopBits::One, + 2 => StopBits::Two, + _ => { return Err(format!( + "error: the stop bits of data specified is incorrect + (type 1 or 2)")); + } + }; + + let flow_ctrl = match flow_ctrl_ { + "None" => FlowControl::None, + "Software" => FlowControl::Software, + "Hardware" => FlowControl::Hardware, + _ => { return Err(format!( + "error: the parity of data specified is incorrect + (type \"None\", \"Software\" or \"Hardware\")")); + } + }; + + Ok(Self { baud_rate, data_bits, parity, stop_bits, flow_ctrl, timeout_msec }) + } + } + + struct Packet_t { + buf: [u8; MAX_BUF], + size: u32, + } + + impl Packet_t { + pub fn new(buf: [u8; MAX_BUF], size: u32) -> Packet_t { + Packet_t { buf, size } + } + } + + struct Logger { + out: BufWriter, + log_flag: bool, + } + + impl Logger { + fn new>(filename: P, log_flag: bool) -> Result { + let path = Path::new(filename.as_ref()); + + let mut file = match path.exists() { + true => OpenOptions::new().write(true).append(true).open(filename.as_ref())?, + false => File::create(filename.as_ref())? + }; + + let out = BufWriter::new(file); + + Ok(Self { out, log_flag }) + } + + fn log(&mut self, msg: &str) -> Result<(), io::Error> { + if self.log_flag == true { + writeln!(&mut self.out, "{} {};{:?}", + Perf::cur_time("%Y.%m.%d"), + Perf::cur_time("%H:%M:%S.%3f"), + msg.trim())?; + self.out.flush()?; + } + Ok(()) + } + } + + pub struct UartTransact { + type_: Type_en, + port_name: String, + port_settings: PortSettings_t, + tx_packet: String, + rx_packet: String, + + port: Box, + save_data_flag: bool, + save_cmd_flag: bool, + data_writer: Logger, + cmd_writer: Logger, + } + + impl UartTransact { + pub fn new(trans_type: &str, + port_name: &str, + port_settings: PortSettings_t, + save_data_flag: bool, + save_cmd_flag: bool) -> Result { + + let mut type_ = Type_en::tx_rx; + if trans_type == "tx_rx" { type_ = Type_en::tx_rx; } + else if trans_type == "tx" { type_ = Type_en::rx; } + else if trans_type == "rx_tx" { type_ = Type_en::rx_tx; } + else if trans_type == "rx" { type_ = Type_en::rx; } + + let mut filename = format!("../log/data_{}.log", Perf::cur_time("%Y%m%d")); + let data_writer = Logger::new(filename.clone(), save_data_flag)?; + filename = format!("../log/commands_{}.log", Perf::cur_time("%Y%m%d")); + let cmd_writer = Logger::new(filename.clone(), save_data_flag)?; + + let mut port = serialport::new(port_name.clone(), port_settings.baud_rate) + .timeout(Duration::from_millis(port_settings.timeout_msec)).open().unwrap(); + + let tx_packet = String::new(); + let rx_packet = String::new(); + + Ok( Self { type_, port_name: port_name.to_string(), port_settings, save_data_flag, save_cmd_flag, + data_writer, cmd_writer, + port, tx_packet, rx_packet, + }) + } + + + pub fn addPacketForTx(&mut self, buf: String, size: u32) -> Result<(), String> { + if size as usize >= MAX_BUF { + return Err(format!("too much data for transmit! Data size must be < {} bytes", MAX_BUF)); + } + else { self.tx_packet = buf; } + + return Ok(()); + } + + pub fn startTransact(&mut self) -> Result<(), String> { + + if self.type_ == Type_en::tx_rx { + self.cmd_writer.log(&self.tx_packet).unwrap(); + + match self.port.write(&self.tx_packet.as_bytes()) { + Ok(_) => {}, + Err(e) => eprintln!("Error sending data: {}", e), + } + + // self.port.flush().unwrap(); + + let mut reader = BufReader::new(&mut self.port); + + let mut s = String::new(); + if let Err(err) = reader.read_line(&mut s) { + println!("error: {}", err); + return Ok(()); + } + if s.len() > 0 { + self.rx_packet = s.clone(); + self.data_writer.log(&s).unwrap(); + } + } + Ok(()) + } + + pub fn getReceivedPacket(&mut self) -> String { + self.rx_packet.clone() + } + + fn set_port_settings(port_name: &str, + set: PortSettings_t) -> Result, String> { + + let mut port = match serialport::new(port_name, set.baud_rate) + .timeout(Duration::from_millis(set.timeout_msec)).open() { + Ok(p) => p, + Err(msg) => return Err(format!("error: failed to open serial port {} ({})", port_name, msg)), + }; + + match port.set_baud_rate(set.baud_rate) { + Ok(_) => {}, + Err(msg) => return Err(format!("error: failed to open serial port {} ({})", port_name, msg)), + } + match port.set_data_bits(set.data_bits) { + Ok(_) => {}, + Err(msg) => return Err(format!("error: failed to open serial port {} ({})", port_name, msg)), + } + match port.set_parity(set.parity) { + Ok(_) => {}, + Err(msg) => return Err(format!("error: failed to open serial port {} ({})", port_name, msg)), + } + match port.set_stop_bits(set.stop_bits) { + Ok(_) => {}, + Err(msg) => return Err(format!("error: failed to open serial port {} ({})", port_name, msg)), + } + match port.set_flow_control(set.flow_ctrl) { + Ok(_) => {}, + Err(msg) => return Err(format!("error: failed to open serial port {} ({})", port_name, msg)), + } + + return Ok(port); + } + } +} + fn read_str(s: &str) -> Result, String> { let re = match Regex::new(r#""([^"]+)"|(\S+)"#) { Ok(val) => val, @@ -69,188 +354,15 @@ fn read_str(s: &str) -> Result, String> { Ok(res) } -fn set_port_settings(port_name: &str, baud_rate: u32, data_bits: DataBits, parity: Parity, - stop_bits: StopBits, flow_ctrl: FlowControl, timeout_msec: u64) -> Result, String> { - - let mut port = match serialport::new(port_name, baud_rate) - .timeout(Duration::from_millis(timeout_msec)).open() { - Ok(p) => p, - Err(msg) => return Err(format!("{}", msg)), - }; - - port.set_baud_rate(baud_rate).unwrap(); - port.set_data_bits(data_bits).unwrap(); - port.set_parity(parity).unwrap(); - port.set_stop_bits(stop_bits).unwrap(); - port.set_flow_control(flow_ctrl).unwrap(); - return Ok(port); -} -fn tx_rx_data(port_name: &str, - mut data_out: String, - cmd_writer: &mut BufWriter, - data_writer: &mut BufWriter, - save_data_flag: bool, - save_cmd_flag: bool) { - use crate::perf::Perf; - let mut perf = Perf::new(); - perf.start(); - // let port_name = &args[1]; - let mut port = match set_port_settings(port_name, 19200, - DataBits::Eight, - Parity::Even, - StopBits::One, - FlowControl::None, 100) { - Ok(set) => {set}, - Err(msg) => { println!("error while opening com-port ({}): {}", port_name, msg); return } - }; - perf.stop_restart("time open port", "ms"); - - if save_cmd_flag == true { - writeln!(cmd_writer, "{};{};{}", Perf::cur_time("%Y.%m.%d"), - Perf::cur_time("%H:%M:%S.%f"), data_out.trim()).expect("err"); - } - - data_out.push_str(std::str::from_utf8(b"\x0D\x0A").unwrap()); // CR + LF - match port.write(data_out.as_bytes()) { - Ok(_) => {}, - Err(e) => eprintln!("Error sending data: {}", e), - } - - port.flush().unwrap(); - - perf.stop_restart("time write to port", "ms"); - - let mut reader = BufReader::new(port); - let mut s = String::new(); - reader.read_line(&mut s).unwrap(); - if s.len() > 0 { - let data = format!("{}: {}", Perf::cur_time("%H:%M:%S.%f"), s.trim()); - println!("{}", data); - if save_data_flag == true { - writeln!(data_writer, "{}", - format!("{};{};{}", - Perf::cur_time("%Y.%m.%d"), - Perf::cur_time("%H:%M:%S.%f"), - s.trim())) - .expect("err"); - } - } - - perf.stop("time for receive data", "ms"); - - // let mut buffer = Vec::new(); - // match port.read_to_end(&mut buffer) { - // Ok(_) => { - // if buffer.len() > 0 { - // let data = format!("{}: {:?}", cur_time("%H:%M:%S"), buffer); - // println!("{}", data); - // if save_data_flag == true { - // writeln!(data_writer, "{}", - // format!("{};{};{}", - // cur_time("%Y.%m.%d"), - // cur_time("%H:%M:%S"), - // String::from_utf8(buffer).expect("msg"))) - // .expect("err"); - // } - // } - // }, - // Err(msg) => eprintln!("{}", msg), - // } - - // let mut cnt: u32 = 0; - // let mut i = 0; - // let mut buf: String = String::new(); - - // let start = Utc::now(); - // let mut timeout_flag = false; - - // let mut delta1 = 0; - // while cnt == 0 { - // cnt = match port.bytes_to_read() { - // Ok(c) => c, - // Err(msg) => { println!("{}", msg); return; } - // }; - // let delta = Utc::now() - start; - // delta1 = delta.num_microseconds().unwrap()/1000; - // if delta1 > timeout_ms { - // println!("timeout: {}", delta1); - // timeout_flag = true; - // break; - // }; - // } - - // println!("time (ms): {}", delta1); - - // // println!("time (ms): {:?}", delta.num_microseconds().unwrap()/1000); - - // if timeout_flag == false { - // while i < 500000 { - // // thread::sleep(time::Duration::from_millis(10)); - // i += 1; - // let mut buffer = [0u8; 4096]; - - // cnt = match port.bytes_to_read() { - // Ok(c) => c, - // Err(msg) => { println!("{}", msg); return; } - // }; - - // if cnt > 0 { - // match port.read(&mut buffer) { - // Ok(count) => { - // let s = std::str::from_utf8(&buffer[..count]).unwrap(); - // buf.push_str(s); - // println!("{}", s); - // }, - - // Err(ref e) if e.kind() == io::ErrorKind::TimedOut => { println!("timeout!"); }, - // Err(e) => eprintln!("error reading from port ({}): {}", port_name, e), - // } - // } - // else {} - // } - - // } - - - // if buf.len() > 0 { - // let data = format!("{}: {:?}", cur_time("%H:%M:%S"), buf); - // println!("{}", data); - // if save_data_flag == true { - // writeln!(data_writer, "{};{};{}", cur_time("%Y.%m.%d"), cur_time("%H:%M:%S"), buf.trim()).expect("err"); - // } - // } - -} fn main() { use crate::perf::Perf; + use crate::uartTransact::*; let mut perf = Perf::new(); - let data_log_path = "../log/data.log"; - let file = OpenOptions::new() - .write(true) - .append(true) - .open(data_log_path) - .expect("error opening file "); - - let mut data_writer = BufWriter::new(file); - - let data_log_path = "../log/cmd.log"; - let file = OpenOptions::new() - .write(true) - .append(true) - .open(data_log_path) - .expect("error opening file "); - - let mut cmd_writer = BufWriter::new(file); - - let mut save_data_flag = false; - let mut save_cmd_flag = false; - - let timeout_ms = 1000; let fname_hist = "../settings/cmd_history.log".to_string(); let mut editor = Editor::<()>::new(); if editor.load_history(&fname_hist).is_err() { @@ -281,6 +393,7 @@ fn main() { editor.add_history_entry(&s); + let args = match read_str(&s) { Ok(arg) => arg, Err(msg) => { @@ -296,26 +409,12 @@ fn main() { if cmd_head.contains("exit") { break; } else if cmd_head.contains("help") { println!("Serial port terminal supports the following commands:"); - println!("exit - excecute quit from this program"); - println!("help - explain how to use this program"); - println!("show_ports - shows all available serial ports"); - println!("send - sends specified to "); - println!("send_loop - sends specified to in loop mode: times with period specified in "); - println!("open_port - opens specified with specified settings"); - println!("save_data_log "); - println!("save_cmd_log "); - } - else if cmd_head.contains("save_data_log") { - if args_cnt != 2 { eprintln!("Error while parse command! {}", "arguments count must be 1"); } - - if args[1].contains("enable") { save_data_flag = true; } - else { save_data_flag = false; } - } - else if cmd_head.contains("save_cmd_log") { - if args_cnt != 2 { eprintln!("Error while parse command! {}", "arguments count must be 1"); } - - if args[1].contains("enable") { save_cmd_flag = true; } - else { save_cmd_flag = false; } + println!("\nexit - excecute quit from this program"); + println!("\nhelp - explain how to use this program"); + println!("\nshow_ports - shows all available serial ports"); + println!("\nsend - sends specified "); + println!("\nsend_loop \n\tsends specified to in loop mode: times with period specified in "); + println!("\nopen_port .\n\tExample1: open_port /dev/ttyUSB0 9600 8 Even 1 None 1000 tx_rx true"); } else if cmd_head.contains("show_ports") { match serialport::available_ports() { @@ -330,12 +429,28 @@ fn main() { else if cmd_head == "send" { if args_cnt != 3 { eprintln!("Error while parse command! {}", "arguments count must be 2"); } else { - tx_rx_data(&args[1], - args[2].clone(), - &mut cmd_writer, - &mut data_writer, - save_data_flag, - save_cmd_flag); + let port_name = &args[1]; + let timeout: u64 = 200; + let port_set = PortSettings_t::new(9600, 8, "None", 1, "None", timeout).unwrap(); + let save_data_flag_ = true; + let save_cmd_flag_ = true; + let trans_type = "tx_rx"; + + let mut uartTrans = UartTransact::new(trans_type, port_name, + port_set, save_data_flag_, save_cmd_flag_).unwrap(); + + let mut perf = Perf::new(); + perf.start(); + let mut data_out = args[2].clone(); + data_out.push_str(std::str::from_utf8(b"\x0D\x0A").unwrap()); // CR + LF + + uartTrans.addPacketForTx(data_out.clone(), data_out.len() as u32).unwrap(); + uartTrans.startTransact().unwrap(); + + let s = uartTrans.getReceivedPacket(); + let data = format!("{}: {}", Perf::cur_time("%H:%M:%S.%f"), s.trim()); + println!("{}", data); + perf.stop("time for transaction", "mks"); } } else if cmd_head == "send_loop" { @@ -344,30 +459,33 @@ fn main() { let cnt = args[3].parse::().unwrap(); let period = args[4].parse::().unwrap(); let mut i = 0; - while (i < cnt) { + while i < cnt { i += 1; - tx_rx_data(&args[1], - args[2].clone(), - &mut cmd_writer, - &mut data_writer, - save_data_flag, - save_cmd_flag); - + let mut data_out = args[2].clone(); thread::sleep(time::Duration::from_millis(period)); } } } - else if cmd_head.contains("open port") { + else if cmd_head.contains("open_port") { - if args_cnt != 8 { eprintln!("Error while parse command! {}", "arguments count must be 8"); } + if args_cnt != 10 { eprintln!("Error while parse command! {}", "arguments count must be 9"); } else { - // println!("open port - opens specified with specified settings"); - // let port_name = args[2].clone(); - // let speed = args[3].clone(); - // let data_bits = args[4].clone(); - // let parity = args[5].clone(); - // let stop_bits = args[6].clone(); - // let flow_ctrl = args[7].clone(); + let port_name = &args[1]; + let speed = args[3].parse::().unwrap(); + let data_bits = args[3].parse::().unwrap(); + let parity = &args[4]; + let stop_bits = args[5].parse::().unwrap(); + let flow_ctrl = &args[6]; + let timeout = args[7].parse::().unwrap(); + let trans_type = &args[8]; + let save_data_flag = args[9].parse::().unwrap(); + let save_cmd_flag = save_data_flag; + + let port_set = PortSettings_t::new(speed, data_bits, parity, stop_bits, + flow_ctrl, timeout).unwrap(); + + let mut uartTrans = UartTransact::new(trans_type, &port_name, + port_set, save_data_flag, save_cmd_flag).unwrap(); } } } @@ -377,3 +495,93 @@ fn main() { // drop(port1); } + +fn print_type_of(_: &T) { + println!("{}", std::any::type_name::()); +} + + +// perf.stop("time for transaction", "mks"); + +// let mut buffer = Vec::new(); +// match port.read_to_end(&mut buffer) { +// Ok(_) => { +// if buffer.len() > 0 { +// let data = format!("{}: {:?}", cur_time("%H:%M:%S"), buffer); +// println!("{}", data); +// if save_data_flag == true { +// writeln!(data_writer, "{}", +// format!("{};{};{}", +// cur_time("%Y.%m.%d"), +// cur_time("%H:%M:%S"), +// String::from_utf8(buffer).expect("msg"))) +// .expect("err"); +// } +// } +// }, +// Err(msg) => eprintln!("{}", msg), +// } + +// let mut cnt: u32 = 0; +// let mut i = 0; +// let mut buf: String = String::new(); + +// let start = Utc::now(); +// let mut timeout_flag = false; + +// let mut delta1 = 0; +// while cnt == 0 { +// cnt = match port.bytes_to_read() { +// Ok(c) => c, +// Err(msg) => { println!("{}", msg); return; } +// }; +// let delta = Utc::now() - start; +// delta1 = delta.num_microseconds().unwrap()/1000; +// if delta1 > timeout_ms { +// println!("timeout: {}", delta1); +// timeout_flag = true; +// break; +// }; +// } + +// println!("time (ms): {}", delta1); + +// // println!("time (ms): {:?}", delta.num_microseconds().unwrap()/1000); + +// if timeout_flag == false { +// while i < 500000 { +// // thread::sleep(time::Duration::from_millis(10)); +// i += 1; +// let mut buffer = [0u8; 4096]; + +// cnt = match port.bytes_to_read() { +// Ok(c) => c, +// Err(msg) => { println!("{}", msg); return; } +// }; + +// if cnt > 0 { +// match port.read(&mut buffer) { +// Ok(count) => { +// let s = std::str::from_utf8(&buffer[..count]).unwrap(); +// buf.push_str(s); +// println!("{}", s); +// }, + +// Err(ref e) if e.kind() == io::ErrorKind::TimedOut => { println!("timeout!"); }, +// Err(e) => eprintln!("error reading from port ({}): {}", port_name, e), +// } +// } +// else {} +// } + +// } + + +// if buf.len() > 0 { +// let data = format!("{}: {:?}", cur_time("%H:%M:%S"), buf); +// println!("{}", data); +// if save_data_flag == true { +// writeln!(data_writer, "{};{};{}", cur_time("%Y.%m.%d"), cur_time("%H:%M:%S"), buf.trim()).expect("err"); +// } +// } +