diff --git a/Cargo.lock b/Cargo.lock index bbe8154..2eba9b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -244,6 +244,15 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" +[[package]] +name = "fl2rust" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6679204ae2e70ee854f3caea0085fd15bf413baf81aba85422ea3394b00595f" +dependencies = [ + "fluid-parser", +] + [[package]] name = "flate2" version = "1.0.30" @@ -277,6 +286,12 @@ dependencies = [ "cmake", ] +[[package]] +name = "fluid-parser" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8c1235afc20d2380c8c3bd46ab0bd3f8cda366cc19104f0da9cfc25e8fdf728" + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -1087,6 +1102,7 @@ dependencies = [ "anyhow", "calamine", "chrono", + "fl2rust", "fltk", "lazy_static", "libsqlite3-sys", diff --git a/Cargo.toml b/Cargo.toml index 2431d7f..3876eda 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,13 +6,16 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -anyhow="^1.0.86" +anyhow = "^1.0.86" fltk = { version = "^1.4", features = ["fltk-bundled"] } -calamine="0.25.0" -serialport="4.4.0" -rusqlite="0.25.4" +calamine = "0.25.0" +serialport = "4.4.0" +rusqlite = "0.25.4" libsqlite3-sys = { version = "0.22.2", features = ["bundled"] } -chrono="0.4.38" -log="0.4.22" -once_cell="0.1.8" -lazy_static="1.5.0" \ No newline at end of file +chrono = "0.4.38" +log = "0.4.22" +once_cell = "0.1.8" +lazy_static = "1.5.0" + +[build-dependencies] +fl2rust = "0.5.19" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..4544e7a --- /dev/null +++ b/build.rs @@ -0,0 +1,9 @@ +fn main(){ + use std::path::PathBuf; + use std::env; + + println!("cargo:rerun-if-changed=src/ui/main.fl"); + let g = fl2rust::Generator::default(); + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + g.in_out("src/ui/main.fl", out_path.join("main_ui.rs").to_str().unwrap()).expect("Failed to generate ui code"); +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index 4bb8e2d..0000000 --- a/src/lib.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod services; -mod models; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 12d560d..9a04ac8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,11 @@ use fltk::{prelude::*, window::Window, *}; +use crate::services::ui_service::UiService; +mod services; +mod models; +mod ui; fn main() { let app = app::App::default(); - let mut window = window::Window::new(100, 100, 400, 300, "Hello from rust"); - window.end(); - window.show(); + let mut ui_service = UiService::new(); + ui_service.init_components(); app.run().unwrap(); } diff --git a/src/models/work_model.rs b/src/models/work_model.rs index f6198b8..61079a3 100644 --- a/src/models/work_model.rs +++ b/src/models/work_model.rs @@ -1,5 +1,5 @@ -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct WorkModel{ pub imei: String, pub sn: String, diff --git a/src/services/excel_service.rs b/src/services/excel_service.rs index 8de00a0..0f5979f 100644 --- a/src/services/excel_service.rs +++ b/src/services/excel_service.rs @@ -11,6 +11,9 @@ pub(crate) struct ExcelService { } impl ExcelService { + pub fn get_current_line(&self) -> usize { + return self.current_line; + } pub fn new(file_path: &str) -> Result { let mut work_book: Xlsx<_> = match open_workbook(file_path) { Ok(work_book) => work_book, @@ -57,10 +60,10 @@ impl ExcelService { } work_model.imei = imei.to_string(); } - if let Some(sn) = self.sheet.get((self.current_line, 1)){ + if let Some(sn) = self.sheet.get((self.current_line, 1)) { work_model.sn = sn.to_string(); } - if let Some(line_number) = self.sheet.get((self.current_line, 2)){ + if let Some(line_number) = self.sheet.get((self.current_line, 2)) { work_model.line_number = line_number.to_string(); } self.current_line += 1; diff --git a/src/services/mod.rs b/src/services/mod.rs index 587ae72..1c375c5 100644 --- a/src/services/mod.rs +++ b/src/services/mod.rs @@ -1,6 +1,6 @@ -mod serial_service; -mod sqlite_service; -mod excel_service; -mod ui_service; -mod work_service; -mod log_service; \ No newline at end of file +pub(crate) mod serial_service; +pub(crate) mod sqlite_service; +pub(crate) mod excel_service; +pub(crate) mod ui_service; +pub(crate) mod work_service; +pub(crate) mod log_service; \ No newline at end of file diff --git a/src/services/ui_service.rs b/src/services/ui_service.rs index e69de29..1d30551 100644 --- a/src/services/ui_service.rs +++ b/src/services/ui_service.rs @@ -0,0 +1,82 @@ +use std::cell::RefCell; +use std::rc::Rc; +use fltk::prelude::{InputExt, WidgetExt}; +use crate::models::work_model::WorkModel; +use crate::services::excel_service::ExcelService; +use crate::services::serial_service::SerialService; +use crate::services::work_service::WorkService; +use crate::ui::main_ui; +use crate::ui::main_ui::*; + +pub(crate) struct UiService { + ui: Rc>, + work_service: Rc>, + current_com: String +} + +impl UiService { + pub(crate) fn new() -> Self { + let ui = Rc::new(RefCell::new(main_ui::UserInterface::make_window())); + UiService { ui, work_service: Rc::new(RefCell::new(WorkService::new())), current_com: "".to_string() } + } + + pub(crate) fn init_components(&mut self) { + self.init_excel(); + self.init_start_btn(); + } + + pub fn init_start_btn(&mut self) { + let ui_rc = Rc::clone(&self.ui); + let ui_rc_clone = Rc::clone(&ui_rc); + let work_service_rc = Rc::clone(&self.work_service); + ui_rc.borrow_mut().start_btn.set_callback(move |_| { + let mut ui = ui_rc_clone.borrow_mut(); + let mut work_service = work_service_rc.borrow_mut(); + match work_service.excel_service { + None => { + fltk::dialog::message_default("Please Select Excel File First;"); + return; + } + Some(_) => {} + } + let selected_com = ui.com_textbox.value(); + if let Err(msg) = work_service.init_serial_service(selected_com) { + fltk::dialog::message_default(&msg); + return; + } + if let Some(mut model) = work_service.get_next_work_model() { + ui.current_write_model.set_value(&format!("{}: {}_{}", &model.line_number, &model.imei, &model.sn)); + match work_service.write_and_check(model) { + Ok(_) => {} + Err(msg) => { fltk::dialog::message_default(&msg) } + } + } + }); + } + + fn init_excel(&mut self) { + let ui_rc = Rc::new(&self.ui); + let ui_clone = Rc::clone(&self.ui); + let work_service_clone = Rc::clone(&self.work_service); + ui_rc.borrow_mut().select_file_btn.set_callback(move |_| { + let mut ui = ui_clone.borrow_mut(); + let mut work_service = work_service_clone.borrow_mut(); + let mut dialog = fltk::dialog::FileDialog::new(fltk::dialog::FileDialogType::BrowseFile); + dialog.show(); + let binding = dialog.filename(); + let path = binding.to_str().unwrap(); + let current_line = &work_service.get_current_line().to_string(); + work_service.init_excel_service(path.to_string()).unwrap(); + ui.excel_file_textbox.set_value(path); + ui.current_line_textbox.set_value(current_line); + }); + } + + fn init_serial_service(&mut self) { + let port_name = self.ui.borrow().com_textbox.value(); + match self.work_service.borrow_mut().init_serial_service(port_name) { + Ok(_) => {} + Err(_) => { fltk::dialog::message_default("Cant Open serial") } + } + } +} \ No newline at end of file diff --git a/src/services/work_service.rs b/src/services/work_service.rs index 46731d0..3ae4a28 100644 --- a/src/services/work_service.rs +++ b/src/services/work_service.rs @@ -3,61 +3,100 @@ use crate::models::work_model::WorkModel; use crate::services::{serial_service::SerialService, sqlite_service::SqliteService, excel_service::ExcelService}; pub struct WorkService { - serial_service: SerialService, + pub(crate) serial_service: Option, sqlite_service: SqliteService, - excel_service: ExcelService, + pub(crate) excel_service: Option, } impl WorkService { - + pub fn new() -> Self { + WorkService { + serial_service: Option::None, + sqlite_service: SqliteService::new("data.db".to_string()).unwrap(), + excel_service: Option::None, + } + } pub fn get_port_names() -> Vec { //maybe should not use unwrap - return SerialService::get_ports().unwrap() + return SerialService::get_ports().unwrap(); } - fn init_excel_service(&mut self, path: String)->Result{ + pub fn init_excel_service(&mut self, path: String) -> Result { return if let Ok(excel_service) = ExcelService::new(&path) { - self.excel_service = excel_service; + self.excel_service = Some(excel_service); Ok(true) } else { Err("Cant Init ExcelService".to_string()) - } + }; } - fn init_sqlite_service(&mut self, db_path: String)->Result{ + pub fn write_and_check(&mut self, model: WorkModel) -> Result { + fltk::dialog::message_default(&format!("{}:{}:{}", model.imei, model.sn, model.line_number)); + Ok(true) + } + + pub fn get_current_line(&mut self) -> usize { + if let Some(service) = &mut self.excel_service { + return service.get_current_line(); + } + return 0; + } + + pub fn get_next_work_model(&mut self) -> Option { + if let Some(service) = &mut self.excel_service { + if let Ok(model) = service.get_next_work_model() { + return Some(model); + } else { return None; } + } + return None; + } + + pub fn init_sqlite_service(&mut self, db_path: String) -> Result { return if let Ok(sqlite_service) = SqliteService::new(db_path) { self.sqlite_service = sqlite_service; Ok(true) } else { Err("Cant Init SqliteService".to_string()) - } + }; } - fn init_serial_service(&mut self, port_name: String)->Result{ + pub fn init_serial_service(&mut self, port_name: String) -> Result { return if let Ok(serial_service) = SerialService::new(&port_name) { - self.serial_service = *serial_service; + self.serial_service = Some(*serial_service); Ok(true) } else { Err("Cant Init SerialService".to_string()) - } + }; } fn write_imei(&mut self, imei: String) -> Result { let write_imei_command = format!("AT+ECCGSN=\"IMEI\",\"{}\"", imei); - return self.serial_service.send_command_with_target(write_imei_command, None, "OK".to_string()); + if let Some(service) = &mut self.serial_service { + return service.send_command_with_target(write_imei_command, None, "OK".to_string()); + } + return Err("Cant Init SerialService".to_string()); } fn write_sn(&mut self, sn: String) -> Result { let write_sn_command = format!("AT+ECCGSN=\"SN\",\"{}\"", sn); - return self.serial_service.send_command_with_target(write_sn_command, None, "OK".to_string()); + if let Some(service) = &mut self.serial_service { + return service.send_command_with_target(write_sn_command, None, "OK".to_string()); + } + return Err("Cant Init SerialService".to_string()); } fn check_imei(&mut self, imei: &str) -> Result { let check_imei_command = "AT+CGSN=1".to_string(); - return self.serial_service.send_command_with_target(check_imei_command, None, imei.to_string()); + if let Some(service) = &mut self.serial_service { + return service.send_command_with_target(check_imei_command, None, imei.to_string()); + } + return Err("Cant Init SerialService".to_string()); } fn check_sn(&mut self, sn: &str) -> Result { let check_sn_command = "AT+CGSN=0".to_string(); - return self.serial_service.send_command_with_target(check_sn_command, None, sn.to_string()); + if let Some(service) = &mut self.serial_service { + return service.send_command_with_target(check_sn_command, None, sn.to_string()); + } + return Err("Cant Init ServialService".to_string()); } } \ No newline at end of file diff --git a/src/ui/event_handle.rs b/src/ui/event_handle.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/ui/main_ui.rs b/src/ui/main_ui.rs new file mode 100644 index 0000000..70bdc32 --- /dev/null +++ b/src/ui/main_ui.rs @@ -0,0 +1,5 @@ +#![allow(unused_imports)] +#![allow(unused_mut)] +#![allow(unused_variables)] +#![allow(clippy::needless_update)] +include!(concat!(env!("OUT_DIR"), "/main_ui.rs")); diff --git a/src/ui/mod.rs b/src/ui/mod.rs new file mode 100644 index 0000000..c345219 --- /dev/null +++ b/src/ui/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod main_ui; +mod event_handle; \ No newline at end of file