314 lines
12 KiB
Rust
314 lines
12 KiB
Rust
#![windows_subsystem = "windows"]
|
|
mod port;
|
|
|
|
use closure::closure;
|
|
|
|
use gtk::{Inhibit, TextView, Statusbar, Label};
|
|
use gtk::{gio, glib};
|
|
use gtk::prelude::{GtkWindowExt, BuilderExtManual, GtkMenuItemExt, WidgetExt, EntryExt, TextBufferExt};
|
|
use gio::prelude::{ApplicationExt, ApplicationExtManual};
|
|
use std::sync::mpsc::{Sender, Receiver, channel};
|
|
use serialport::{StopBits, FlowControl, Parity, DataBits};
|
|
use crate::port::*;
|
|
use gtk::prelude::TextViewExt;
|
|
use gtk::prelude::LabelExt;
|
|
|
|
fn main() {
|
|
let application = gtk::Application::new(
|
|
Some("com.github.gtk-rs.examples.menu_bar_system"),
|
|
Default::default(),
|
|
);
|
|
// application.connect_startup(|app| {
|
|
// });
|
|
application.connect_activate(build_ui);
|
|
|
|
application.run();
|
|
}
|
|
|
|
fn build_ui(application: >k::Application) {
|
|
let builder = gtk::Builder::from_string(include_str!("test.ui"));
|
|
let main_window: gtk::ApplicationWindow = builder.object("main_window").expect("Can not get window!");
|
|
main_window.set_application(Some(application));
|
|
let menu_view_command: gtk::MenuItem = builder.object("view_command").expect("Can not get command item");
|
|
let command_entry: gtk::Entry = builder.object("command_entry").expect("Can not get command entry");
|
|
let tmp = command_entry.clone();
|
|
menu_view_command.connect_activate(move |_| {
|
|
if WidgetExt::is_visible(&tmp) {
|
|
tmp.hide();
|
|
} else {
|
|
tmp.show();
|
|
tmp.set_has_focus(true);
|
|
}
|
|
});
|
|
let log_window: gtk::Window = builder.object("log_window").expect("Can not get log view");
|
|
let menu_log_command: gtk::MenuItem = builder.object("log_command").expect("Can not get log command");
|
|
let ui_receive_view: TextView = builder.object("receive_view").expect("can not get receive view");
|
|
let ui_baudrate: Label = builder.object("ui_baudrate").unwrap();
|
|
let ui_databit: Label = builder.object("ui_databit").unwrap();
|
|
let ui_parity: Label = builder.object("ui_parity").unwrap();
|
|
let ui_stopbit: Label = builder.object("ui_stopbit").unwrap();
|
|
let ui_statusbar: Statusbar = builder.object("statusbar").unwrap();
|
|
let ui_log_view: TextView = builder.object("log_view").unwrap();
|
|
|
|
log_window.show();
|
|
log_window.connect_delete_event(|a, _| {
|
|
a.hide();
|
|
Inhibit(true)
|
|
});
|
|
let tmp = log_window.clone();
|
|
menu_log_command.connect_activate(move |_| {
|
|
if tmp.is_visible() {
|
|
tmp.hide();
|
|
} else {
|
|
tmp.show();
|
|
}
|
|
});
|
|
let (sender_ui_upd, receiver_ui_upd) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
|
receiver_ui_upd.attach(None, move |msg| {
|
|
match msg {
|
|
Message::UiUpdateLog(text) => {
|
|
let buf = ui_log_view.buffer().unwrap();
|
|
buf.insert(&mut buf.end_iter(), text.as_str());
|
|
}
|
|
Message::UiUpdateReceiveMsg(text) => {
|
|
let buf = ui_receive_view.buffer().unwrap();
|
|
buf.insert(&mut buf.end_iter(), text.as_str());
|
|
ui_receive_view.scroll_to_mark(&buf.get_insert().unwrap(), 0.0, true, 0.5, 0.5);
|
|
}
|
|
Message::UiCleanReceiveMsg => ui_receive_view.buffer().unwrap().set_text(""),
|
|
Message::UiCleanLog => ui_log_view.buffer().unwrap().set_text(""),
|
|
Message::UiShowLog => log_window.show(),
|
|
Message::UiHideLog => log_window.hide(),
|
|
Message::UiUpdateStatusBarBaudrate(value) => ui_baudrate.set_text(value.to_string().as_str()),
|
|
Message::UiUpdateStatusBarDatabit(value) => ui_databit.set_text(value.to_string().as_str()),
|
|
Message::UiUpdateStatusBarParity(value) => ui_parity.set_text(value.to_string().as_str()),
|
|
Message::UiUpdateStatusBarStopbit(value) => ui_stopbit.set_text(value.to_string().as_str()),
|
|
_ => {}
|
|
}
|
|
glib::Continue(true)
|
|
});
|
|
|
|
let (gui2main_tx, gui2main_rx) = channel::<Message>();
|
|
std::thread::spawn(closure!(clone gui2main_tx, clone sender_ui_upd, || {main_proc(gui2main_tx, gui2main_rx, sender_ui_upd)}));
|
|
|
|
|
|
let to_ui = sender_ui_upd.clone();
|
|
command_entry.connect_activate(move |x| {
|
|
let command_buf = x.buffer();
|
|
let command = command_buf.text();
|
|
command_buf.set_text("");
|
|
process_cmd(command, to_ui.clone(), gui2main_tx.clone());
|
|
});
|
|
|
|
main_window.show();
|
|
}
|
|
|
|
|
|
fn process_cmd(command: String, to_ui: glib::Sender<Message>, gui2main_tx: Sender<Message>) {
|
|
let command_split: Vec<&str> = command.split_whitespace().collect();
|
|
if command_split.len() != 0 {
|
|
let cmd = command_split[0].to_ascii_lowercase();
|
|
match cmd.as_str() {
|
|
"set" => {
|
|
if command_split.len() == 1 {
|
|
to_ui.send(Message::UiUpdateLog("No enough argument\n".to_string())).unwrap();
|
|
} else {
|
|
let args: Vec<String> = command_split[1..].to_vec().into_iter().map(|item| String::from(item)).collect();
|
|
gui2main_tx.send(Message::MainCmdSet(args)).unwrap();
|
|
}
|
|
}
|
|
"open" => {
|
|
if command_split.len() == 1 {
|
|
to_ui.send(Message::UiUpdateLog("No enough argument\n".to_string())).unwrap();
|
|
} else {
|
|
let args: Vec<String> = command_split[1..].to_vec().into_iter().map(|item| String::from(item)).collect();
|
|
gui2main_tx.send(Message::MainCmdOpen(args[0].clone())).unwrap();
|
|
}
|
|
}
|
|
"close" => {
|
|
gui2main_tx.send(Message::MainCmdClose).unwrap();
|
|
}
|
|
"list" => {
|
|
to_ui.send(Message::UiUpdateLog(list_available_ports())).unwrap();
|
|
}
|
|
"send" => {
|
|
gui2main_tx.send(Message::MainCmdSend(command[5..].parse().unwrap())).unwrap();
|
|
}
|
|
"clean" => {
|
|
to_ui.send(Message::UiCleanReceiveMsg).unwrap();
|
|
to_ui.send(Message::UiCleanLog).unwrap();
|
|
}
|
|
"show" => {
|
|
if command_split.len() == 1 {
|
|
to_ui.send(Message::UiUpdateLog("No enough argument\n".to_string())).unwrap();
|
|
} else {
|
|
match command_split[1] {
|
|
"log" => { to_ui.send(Message::UiShowLog).unwrap(); }
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
"hide" => {
|
|
if command_split.len() == 1 {
|
|
to_ui.send(Message::UiUpdateLog("No enough argument\n".to_string())).unwrap();
|
|
} else {
|
|
match command_split[1] {
|
|
"log" => { to_ui.send(Message::UiHideLog).unwrap(); }
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn main_proc(to_main_tx: Sender<Message>, rx: Receiver<Message>, ui_upd: glib::Sender<Message>) {
|
|
let (mut main2port_tx, _rx_port_receive) = channel::<Message>();
|
|
let mut port_default_config = PortConfig {
|
|
baud_rate: 115_200,
|
|
data_bits: DataBits::Eight,
|
|
parity: Parity::None,
|
|
flow_control: FlowControl::None,
|
|
stopbit: StopBits::One,
|
|
timeout: 10,
|
|
};
|
|
loop {
|
|
if let Ok(msg) = rx.try_recv() {
|
|
match msg {
|
|
Message::UiCleanReceiveMsg => {}
|
|
Message::MainCmdOpen(arg) => {
|
|
let (tmp_to_port, main2port_rx) = channel::<Message>();
|
|
main2port_tx = tmp_to_port;
|
|
match port_open(arg, port_default_config) {
|
|
Ok(port) => {
|
|
std::thread::spawn(closure!(clone to_main_tx, || port_proc(port, to_main_tx, main2port_rx)));
|
|
ui_upd.send(Message::UiUpdateLog("open Port succeed\n".to_string())).unwrap();
|
|
}
|
|
Err(e) => {
|
|
match e {
|
|
Error::PortOpenFailed(msg) => {
|
|
ui_upd.send(Message::UiUpdateLog(msg)).unwrap();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Message::MainCmdClose => {
|
|
main2port_tx.send(Message::PortCmdClose).unwrap();
|
|
}
|
|
Message::MainCmdSend(msg) => {
|
|
main2port_tx.send(Message::PortCmdSend(msg)).unwrap();
|
|
}
|
|
Message::MainCmdSet(args) => {
|
|
match args[0].as_str() {
|
|
"baudrate" => {
|
|
if args.len() != 2 {
|
|
ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap();
|
|
} else {
|
|
if let Ok(value) = args[1].parse::<u32>() {
|
|
port_default_config.baud_rate = value;
|
|
ui_upd.send(Message::UiUpdateStatusBarBaudrate(value)).unwrap();
|
|
} else {
|
|
ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap();
|
|
}
|
|
}
|
|
}
|
|
"databit" => {
|
|
if args.len() != 2 {
|
|
ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap();
|
|
} else {
|
|
if let Ok(value) = args[1].parse::<u32>() {
|
|
ui_upd.send(Message::UiUpdateStatusBarDatabit(value)).unwrap();
|
|
match value {
|
|
8 => port_default_config.data_bits = DataBits::Eight,
|
|
7 => port_default_config.data_bits = DataBits::Seven,
|
|
6 => port_default_config.data_bits = DataBits::Six,
|
|
5 => port_default_config.data_bits = DataBits::Five,
|
|
_ => { ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap(); }
|
|
}
|
|
} else {
|
|
ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap();
|
|
}
|
|
}
|
|
}
|
|
"parity" => {
|
|
if args.len() != 2 {
|
|
ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap();
|
|
} else {
|
|
if let Ok(value) = args[1].parse::<u32>() {
|
|
match value {
|
|
0 => {
|
|
port_default_config.parity = Parity::None;
|
|
ui_upd.send(Message::UiUpdateStatusBarParity("None".to_string())).unwrap();
|
|
}
|
|
1 => {
|
|
port_default_config.parity = Parity::Odd;
|
|
ui_upd.send(Message::UiUpdateStatusBarParity("Odd".to_string())).unwrap();
|
|
}
|
|
2 => {
|
|
port_default_config.parity = Parity::Even;
|
|
ui_upd.send(Message::UiUpdateStatusBarParity("Even".to_string())).unwrap();
|
|
}
|
|
_ => { ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap(); }
|
|
}
|
|
} else {
|
|
ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap();
|
|
}
|
|
}
|
|
}
|
|
"stopbit" => {
|
|
if args.len() != 2 {
|
|
ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap();
|
|
} else {
|
|
if let Ok(value) = args[1].parse::<u32>() {
|
|
ui_upd.send(Message::UiUpdateStatusBarStopbit(value)).unwrap();
|
|
match value {
|
|
1 => port_default_config.stopbit = StopBits::One,
|
|
2 => port_default_config.stopbit = StopBits::Two,
|
|
_ => { ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap(); }
|
|
}
|
|
} else {
|
|
ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap();
|
|
}
|
|
}
|
|
}
|
|
"flowcontrol" => {
|
|
if args.len() != 2 {
|
|
ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap();
|
|
} else {
|
|
match args[1].as_str() {
|
|
"hard" => port_default_config.flow_control = FlowControl::Hardware,
|
|
"soft" => port_default_config.flow_control = FlowControl::Software,
|
|
"none" => port_default_config.flow_control = FlowControl::None,
|
|
_ => { ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap(); }
|
|
}
|
|
}
|
|
}
|
|
_ => { ui_upd.send(Message::UiUpdateLog("command does not support!\n".to_string())).unwrap(); }
|
|
}
|
|
}
|
|
Message::PortHaveData(data) => {
|
|
let mut message_show = String::new();
|
|
for i in data {
|
|
// let char = i as char;
|
|
// // let char = 'i';
|
|
if i.is_ascii_alphanumeric() || i.is_ascii_whitespace() || i.is_ascii_punctuation() || i.is_ascii_graphic() {
|
|
message_show.push(i as char);
|
|
}
|
|
}
|
|
// ui_upd.send(Message::UiUpdateReceiveMsg(String::from_utf8_lossy(&*data).parse().unwrap())).unwrap();
|
|
ui_upd.send(Message::UiUpdateReceiveMsg(message_show)).unwrap();
|
|
}
|
|
Message::PortCloseSucceed => {
|
|
ui_upd.send(Message::UiUpdateLog("Close port succeed\n".to_string())).unwrap();
|
|
}
|
|
Message::PortError(msg) => {
|
|
ui_upd.send(Message::UiUpdateLog(format!("port closed by error: {}", msg))).unwrap();
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
}
|