From 7d96d889ec41dfd8a63b8a7c7af1ec5522b9175f Mon Sep 17 00:00:00 2001 From: Shadowbee27 Date: Wed, 31 Dec 2025 16:36:23 +0100 Subject: [PATCH] Switch barcode flow to blocking IO and bump deps Convert barcode types to i64 and add a manual input field. Remove the tokio Runtime and use reqwest::blocking for Google Books. Adjust serial handling (Sender, added logging, shorter recv timeout, clear port on disconnect, and faster UI repaint to prevent "app not responding"). Bump reqwest to 0.13.1, serde_json to 1.0.148 and update Cargo.lock with required TLS/quinn deps. --- Cargo.lock | 244 ++++++++++++++++++++++++++++++- Cargo.toml | 4 +- src/app/app.rs | 36 +++-- src/app/bookdata.rs | 6 +- src/app/serial_read.rs | 16 +- src/book_data/google.rs | 49 ++++--- src/food_data/open_food_facts.rs | 2 +- 7 files changed, 302 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a5639b3..23f0f56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -560,6 +560,28 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "aws-lc-rs" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a88aab2464f1f25453baa7a07c84c5b7684e274054ba06817f382357f77a288" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45afffdee1e7c9126814751f88dddc747f41d91da16c9551a0f1e8a11e788a1" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "barcode-analyser" version = "0.1.0" @@ -573,7 +595,7 @@ dependencies = [ "log", "open-library", "openfoodfacts", - "reqwest 0.12.28", + "reqwest 0.13.1", "serde", "serde_json", "serial", @@ -822,6 +844,15 @@ dependencies = [ "error-code", ] +[[package]] +name = "cmake" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +dependencies = [ + "cc", +] + [[package]] name = "codespan-reporting" version = "0.12.0" @@ -1557,6 +1588,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures-channel" version = "0.3.31" @@ -1649,8 +1686,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -1660,9 +1699,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasip2", + "wasm-bindgen", ] [[package]] @@ -2513,6 +2554,12 @@ dependencies = [ "imgref", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "malloc_buf" version = "0.0.6" @@ -2655,10 +2702,10 @@ dependencies = [ "libc", "log", "openssl", - "openssl-probe", + "openssl-probe 0.1.6", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] @@ -3171,6 +3218,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-probe" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" + [[package]] name = "openssl-sys" version = "0.9.111" @@ -3512,6 +3565,62 @@ dependencies = [ "memchr", ] +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.1", + "rustls", + "socket2 0.6.1", + "thiserror 2.0.17", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "aws-lc-rs", + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash 2.1.1", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.17", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.6.1", + "tracing", + "windows-sys 0.60.2", +] + [[package]] name = "quote" version = "1.0.42" @@ -3808,6 +3917,48 @@ dependencies = [ "web-sys", ] +[[package]] +name = "reqwest" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04e9018c9d814e5f30cc16a0f03271aeab3571e609612d9fe78c1aa8d11c2f62" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.4.12", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.8.1", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "mime", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "serde", + "serde_json", + "sync_wrapper 1.0.2", + "tokio", + "tokio-rustls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "rgb" version = "0.8.52" @@ -3872,6 +4023,7 @@ version = "0.23.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ + "aws-lc-rs", "once_cell", "rustls-pki-types", "rustls-webpki", @@ -3879,6 +4031,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +dependencies = [ + "openssl-probe 0.2.0", + "rustls-pki-types", + "schannel", + "security-framework 3.5.1", +] + [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -3894,15 +4058,44 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" dependencies = [ + "web-time", "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +dependencies = [ + "core-foundation 0.10.0", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework 3.5.1", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -3976,6 +4169,19 @@ dependencies = [ "security-framework-sys", ] +[[package]] +name = "security-framework" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +dependencies = [ + "bitflags 2.10.0", + "core-foundation 0.10.0", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + [[package]] name = "security-framework-sys" version = "2.15.0" @@ -4018,9 +4224,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.147" +version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af14725505314343e673e9ecb7cd7e8a36aa9791eb936235a3567cc31447ae4" +checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" dependencies = [ "itoa", "memchr", @@ -4505,6 +4711,21 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.48.0" @@ -5056,6 +5277,15 @@ dependencies = [ "web-sys", ] +[[package]] +name = "webpki-root-certs" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee3e3b5f5e80bc89f30ce8d0343bf4e5f12341c51f3e26cbeecbc7c85443e85b" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "weezl" version = "0.1.12" @@ -6106,9 +6336,9 @@ dependencies = [ [[package]] name = "zmij" -version = "0.1.9" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0095ecd462946aa3927d9297b63ef82fb9a5316d7a37d134eeb36e58228615a" +checksum = "e6d6085d62852e35540689d1f97ad663e3971fc19cf5eceab364d62c646ea167" [[package]] name = "zune-core" diff --git a/Cargo.toml b/Cargo.toml index f1352be..63d312b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,8 +35,8 @@ strip = "debuginfo" [dependencies] tokio = { version = "1.48.0", features = ["full"] } -reqwest = { version = "0.12.28", features = ["json"] } -serde_json = "1.0.147" +reqwest = { version = "0.13.1", features = ["json", "blocking"] } +serde_json = "1.0.148" serde = { version = "1.0.228", features = ["derive"] } log = "0.4.29" env_logger = "0.11.8" diff --git a/src/app/app.rs b/src/app/app.rs index ed2362e..629a756 100644 --- a/src/app/app.rs +++ b/src/app/app.rs @@ -12,7 +12,6 @@ use std::{ }; use strum::IntoEnumIterator; use strum_macros::EnumIter; -use tokio::runtime::Runtime; #[derive(Default, Debug, PartialEq, EnumIter, Clone)] enum ScannerSetting { @@ -29,9 +28,10 @@ pub struct BarcodeScanner { open_food_facts_data: Data, new_port: String, pub port: String, - pub current_barcode: i32, - last_barcode: i32, - serial_rx: Option>, + pub current_barcode: i64, + man_barcode: String, + last_barcode: i64, + serial_rx: Option>, serial_handle: Option>, } @@ -49,22 +49,27 @@ impl std::fmt::Display for ScannerSetting { impl eframe::App for BarcodeScanner { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - let runtime = Runtime::new().unwrap(); - egui_extras::install_image_loaders(ctx); egui::CentralPanel::default().show(ctx, |ui| { ui.heading("Barcode Scanner"); // Get check if we got a new Barcode and get the needed data if self.current_barcode != self.last_barcode { info!("Getting new data for barcode: {}", self.current_barcode); - let openfoodfacts_future = get_open_food_facts_data(self.current_barcode); - let googlebookapi_future = get_google_book_data(self.current_barcode); + self.google_book_data = get_google_book_data(self.current_barcode); + self.open_food_facts_data = get_open_food_facts_data(self.current_barcode); self.last_barcode = self.current_barcode; - self.open_food_facts_data = Runtime::block_on(&runtime, openfoodfacts_future); - self.google_book_data = Runtime::block_on(&runtime, googlebookapi_future); } // Display the current barcode ui.label(format!("Barcode: {}", &self.last_barcode.to_string())); + if self.scanner_setting == ScannerSetting::Manual { + let man_barcode_field = ui.text_edit_singleline(&mut self.man_barcode); + if !man_barcode_field.has_focus() + && !self.man_barcode.is_empty() + && self.current_barcode.to_string() != self.man_barcode + { + self.current_barcode = self.man_barcode.trim().parse::().unwrap(); + } + } // Columns for data sources ui.columns(2, |column| { @@ -106,12 +111,10 @@ impl eframe::App for BarcodeScanner { let port = ui.text_edit_singleline(&mut self.new_port); if !port.has_focus() && !self.new_port.is_empty() && self.new_port != self.port { self.port = self.new_port.clone(); - let (tx, rx) = mpsc::channel(); + let (tx, rx) = mpsc::channel::(); let port_clone = self.port.clone(); self.serial_rx = Some(rx); self.serial_handle = Some(thread::spawn(move || read_serial(port_clone, tx))); - // TODO! - // let task = tokio::spawn(async move { println!("Serial Port change") }); } if self.port.is_empty() { @@ -123,13 +126,14 @@ impl eframe::App for BarcodeScanner { // Check the recv if we got new data. If the recv is disconected we panic as this is not supose to happen if self.scanner_setting == ScannerSetting::Serial && !self.port.is_empty() { match &self.serial_rx { - Some(v) => match v.recv_timeout(Duration::from_secs(1)) { + Some(v) => match v.recv_timeout(Duration::from_millis(10)) { Ok(recv) => { self.current_barcode = recv; } Err(e) => { if e == RecvTimeoutError::Disconnected { - panic!("Serial Port is inialized but no reciver is active"); + self.port = String::new(); + self.new_port = String::new(); } } }, @@ -137,6 +141,6 @@ impl eframe::App for BarcodeScanner { } } }); - ctx.request_repaint_after(Duration::from_millis(100)); + ctx.request_repaint_after(Duration::from_millis(50)); } } diff --git a/src/app/bookdata.rs b/src/app/bookdata.rs index 615bd96..c8b8ab1 100644 --- a/src/app/bookdata.rs +++ b/src/app/bookdata.rs @@ -2,8 +2,8 @@ use serde::Serialize; #[allow(unused)] #[derive(Debug, Clone, Serialize)] -pub struct BookData<'a> { - pub title: &'a String, +pub struct BookData { + pub title: String, pub authors: Vec, pub description: String, } @@ -13,7 +13,7 @@ pub struct Data { pub data: String, } -impl<'a> std::fmt::Display for BookData<'a> { +impl std::fmt::Display for BookData { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, diff --git a/src/app/serial_read.rs b/src/app/serial_read.rs index f9badec..be80db6 100644 --- a/src/app/serial_read.rs +++ b/src/app/serial_read.rs @@ -16,7 +16,11 @@ pub fn read_serial(port: String) { } #[cfg(any(target_os = "linux", target_os = "macos"))] -pub fn read_serial(port: String, tx: mpsc::Sender) { +pub fn read_serial(port: String, tx: mpsc::Sender) { + info!("Your log level is set to info"); + debug!("Your log level is set to debug"); + warn!("Your log level is set to warn"); + error!("Your log level is set to error"); let mut port = serial::open(&port).unwrap(); port .reconfigure(&|settings| { @@ -30,15 +34,13 @@ pub fn read_serial(port: String, tx: mpsc::Sender) { .unwrap(); loop { - port.set_timeout(Duration::from_millis(1000)).unwrap(); - port.set_timeout(Duration::from_millis(1000000000)).unwrap(); let buf: &mut [u8; 14] = &mut [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + info!("Reading from Port"); port.read_exact(buf).unwrap(); let barcode_id = from_utf8(buf).unwrap(); - debug!("{}", &barcode_id); - if let Ok(val) = barcode_id.trim().parse::() { - let _ = tx.send(val); - } + info!("{}", &barcode_id); + info!("Sending barcode: {}", &barcode_id); + let _ = tx.send(barcode_id.trim().parse::().unwrap()); } } diff --git a/src/book_data/google.rs b/src/book_data/google.rs index 305dc4b..568769a 100644 --- a/src/book_data/google.rs +++ b/src/book_data/google.rs @@ -1,5 +1,5 @@ use crate::app::bookdata::{BookData, Data}; -use reqwest::Client; +use reqwest::blocking::Client; use serde::{Deserialize, Serialize}; #[allow(unused)] @@ -30,46 +30,57 @@ struct ImageLinks { smallThumbnail: Option, } -pub async fn get_google_book_data(ean13: i32) -> Data { +pub fn get_google_book_data(ean13: i64) -> Data { let url = format!( "https://www.googleapis.com/books/v1/volumes?q=isbn:{}", ean13, ); - let cleint = Client::new(); - let bookdata = cleint - .get(url) + let client = Client::new(); + let result = client + .get(&url) .send() - .await - .unwrap() - .json::() - .await - .unwrap(); + .and_then(|resp| resp.json::()); - Data { - has_data: true, - data: convert_to_string(bookdata.items.first().unwrap()).await, + match result { + Ok(bookroot) => { + if let Some(item) = bookroot.items.first() { + Data { + has_data: true, + data: convert_to_string(item), + } + } else { + Data { + has_data: false, + data: String::new(), + } + } + } + Err(_) => Data { + has_data: false, + data: String::new(), + }, } } -async fn convert_to_string(data: &Item) -> String { - let mut data = data.clone(); +fn convert_to_string(data: &Item) -> String { + let data = data.clone(); let bookdata = data.to_bookdata(); format!("{}", bookdata) } impl Item { - pub fn to_bookdata(&mut self) -> BookData<'_> { + pub fn to_bookdata(self) -> BookData { let mut authors: Vec = Vec::new(); let mut description = String::new(); - if let Some(se) = self.volumeInfo.authors.take() { + if let Some(se) = self.volumeInfo.authors { authors = se; } - if let Some(se) = self.volumeInfo.description.take() { + if let Some(se) = self.volumeInfo.description { description = se; } BookData { - title: &self.volumeInfo.title, + title: self.volumeInfo.title, authors, description, } diff --git a/src/food_data/open_food_facts.rs b/src/food_data/open_food_facts.rs index 917526d..33b4a37 100644 --- a/src/food_data/open_food_facts.rs +++ b/src/food_data/open_food_facts.rs @@ -4,7 +4,7 @@ use openfoodfacts as off; use serde_json::{Value, json}; use std::collections::HashMap; -pub async fn get_open_food_facts_data(ean13: i32) -> Data { +pub fn get_open_food_facts_data(ean13: i64) -> Data { let mut result = Data::default(); let client = off::v2().build().unwrap(); let data = client.product(ean13.to_string().as_str(), None).unwrap();