From 05fe57bf2408f40ca51695c8fb67d1884273f4b3 Mon Sep 17 00:00:00 2001 From: mattbk Date: Sun, 6 Sep 2026 22:29:24 -0500 Subject: [PATCH 1/5] Rip out all GUI except skeleton. --- src/main.rs | 221 +++++++++++++++++++++++++++------------------------- 1 file changed, 114 insertions(+), 107 deletions(-) diff --git a/src/main.rs b/src/main.rs index 6488039..2f0d55e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,24 +1,24 @@ use eframe::egui; -use serialport::available_ports; +//use serialport::available_ports; use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; -use egui_plot::{Plot, PlotPoints, Points, Text, Line}; +// use egui_plot::{Plot, PlotPoints, Points, Text, Line}; #[derive(Default, Clone)] -struct Satellite { - id: String, - latitude: f64, - longitude: f64, - strength: u8, -} +// struct Satellite { +// id: String, +// latitude: f64, +// longitude: f64, +// strength: u8, +// } -#[derive(Default)] +//#[derive(Default)] struct AppState { - ports: Vec, - selected_port: Option, - satellites: Vec, + //ports: Vec, + //selected_port: Option, + //satellites: Vec, is_reading: bool, // 🔵 NEW: live NMEA data buffer @@ -31,13 +31,13 @@ pub struct MyApp { impl Default for MyApp { fn default() -> Self { - let ports = available_ports() - .map(|ps| ps.into_iter().map(|p| p.port_name).collect()) - .unwrap_or_default(); + // let ports = available_ports() + // .map(|ps| ps.into_iter().map(|p| p.port_name).collect()) + // .unwrap_or_default(); Self { state: Arc::new(Mutex::new(AppState { - ports, + //ports, ..Default::default() })), } @@ -48,36 +48,36 @@ impl Default for MyApp { // Satellite Map Drawing Method // ===================================================================== impl MyApp { - fn draw_satellite_map(&self, ui: &mut egui::Ui, sats: &[Satellite]) { - Plot::new("satellite_map") - .width(300.0) - .height(300.0) - .view_aspect(1.0) - .show(ui, |plot_ui| { - // Draw outline circle - let circle: PlotPoints = (0..360) - .map(|deg| { - let rad = (deg as f64).to_radians(); - [rad.cos(), rad.sin()] - }) - .collect::>() - .into(); + // fn draw_satellite_map(&self, ui: &mut egui::Ui, sats: &[Satellite]) { + // Plot::new("satellite_map") + // .width(300.0) + // .height(300.0) + // .view_aspect(1.0) + // .show(ui, |plot_ui| { + // // Draw outline circle + // let circle: PlotPoints = (0..360) + // .map(|deg| { + // let rad = (deg as f64).to_radians(); + // [rad.cos(), rad.sin()] + // }) + // .collect::>() + // .into(); - plot_ui.line(Line::new(circle)); + // plot_ui.line(Line::new(circle)); - // Draw satellites - for sat in sats { - let az = sat.longitude.to_radians(); - let el = sat.latitude.to_radians(); + // // Draw satellites + // for sat in sats { + // let az = sat.longitude.to_radians(); + // let el = sat.latitude.to_radians(); - let x = el.cos() * az.cos(); - let y = el.cos() * az.sin(); + // let x = el.cos() * az.cos(); + // let y = el.cos() * az.sin(); - plot_ui.points(Points::new(vec![[x, y]]).radius(3.0)); - plot_ui.text(Text::new([x, y].into(), sat.id.clone())); - } - }); - } + // plot_ui.points(Points::new(vec![[x, y]]).radius(3.0)); + // plot_ui.text(Text::new([x, y].into(), sat.id.clone())); + // } + // }); + // } } // ===================================================================== @@ -88,26 +88,28 @@ impl eframe::App for MyApp { let mut state = self.state.lock().unwrap(); // Main panel - egui::CentralPanel::default().show(ctx, |ui| { - ui.heading("Select COM Port"); + // egui::CentralPanel::default().show(ctx, |ui| { + // ui.heading("Select COM Port"); - let ports = state.ports.clone(); + // let ports = state.ports.clone(); - egui::ComboBox::from_label("COM Port") - .selected_text(state.selected_port.as_deref().unwrap_or("Select a Port")) - .show_ui(ui, |cb| { - for port in ports { - cb.selectable_value( - &mut state.selected_port, - Some(port.clone()), - port, - ); - } - }); + // egui::ComboBox::from_label("COM Port") + // .selected_text(state.selected_port.as_deref().unwrap_or("Select a Port")) + // .show_ui(ui, |cb| { + // for port in ports { + // cb.selectable_value( + // &mut state.selected_port, + // Some(port.clone()), + // port, + // ); + // } + // }); - if ui.button("Start Reading").clicked() && !state.is_reading { - if let Some(port_name) = state.selected_port.clone() { - let state_clone = Arc::clone(&self.state); + // if ui.button("Start Reading").clicked() && !state.is_reading { + // if let Some(port_name) = state.selected_port.clone() { + let state_clone = Arc::clone(&self.state); + + let port_name = "/dev/tty.usbmodem1301"; // Thread for GPS streaming thread::spawn(move || { @@ -122,7 +124,7 @@ impl eframe::App for MyApp { match serial.read(&mut buf) { Ok(n) => { let data = String::from_utf8_lossy(&buf[..n]); - let mut satellites = Vec::new(); + // let mut satellites = Vec::new(); for line in data.lines() { @@ -139,24 +141,24 @@ impl eframe::App for MyApp { // Parse GSV if line.starts_with("$GPGSV") { - let fields: Vec<&str> = line.split(',').collect(); - let mut i = 4; + //let fields: Vec<&str> = line.split(',').collect(); + //let mut i = 4; - while i + 3 < fields.len() { - satellites.push(Satellite { - id: fields[i].to_string(), - latitude: fields[i + 1].parse().unwrap_or(0.0), - longitude: fields[i + 2].parse().unwrap_or(0.0), - strength: fields[i + 3].parse().unwrap_or(0), - }); - i += 4; - } + // while i + 3 < fields.len() { + // satellites.push(Satellite { + // id: fields[i].to_string(), + // latitude: fields[i + 1].parse().unwrap_or(0.0), + // longitude: fields[i + 2].parse().unwrap_or(0.0), + // strength: fields[i + 3].parse().unwrap_or(0), + // }); + // i += 4; + // } } } // Update satellites - let mut st = state_clone.lock().unwrap(); - st.satellites = satellites; + //let mut st = state_clone.lock().unwrap(); + // st.satellites = satellites; } Err(_) => break, } @@ -167,51 +169,56 @@ impl eframe::App for MyApp { }); state.is_reading = true; - } - } + // } + // } - ui.separator(); - ui.heading("Satellites"); + // ui.separator(); + // ui.heading("Satellites"); - egui::ScrollArea::vertical().show(ui, |ui| { - for sat in &state.satellites { - ui.horizontal(|ui| { - ui.label(format!("ID: {}", sat.id)); - ui.label(format!("Elv: {:.2}", sat.latitude)); - ui.label(format!("Azm: {:.2}", sat.longitude)); - ui.label(format!("Strength: {}", sat.strength)); - }); - } - }); - }); + // egui::ScrollArea::vertical().show(ui, |ui| { + // for sat in &state.satellites { + // ui.horizontal(|ui| { + // ui.label(format!("ID: {}", sat.id)); + // ui.label(format!("Elv: {:.2}", sat.latitude)); + // ui.label(format!("Azm: {:.2}", sat.longitude)); + // ui.label(format!("Strength: {}", sat.strength)); + // }); + // } + // }); + // }); // ===================================================================== // NEW: Live GPS Stream Window // ===================================================================== - egui::Window::new("GPS Stream") - .default_width(400.0) - .default_height(300.0) - .resizable(true) - .show(ctx, |ui| { - ui.label("Live NMEA Data:"); + // egui::Window::new("GPS Stream") + // .default_width(400.0) + // .default_height(300.0) + // .resizable(true) + // .show(ctx, |ui| { + // ui.label("Live NMEA Data:"); - egui::ScrollArea::vertical() - .stick_to_bottom(true) - .show(ui, |ui| { - for line in &state.nmea_log { - ui.monospace(line); - } - }); - }); + // egui::ScrollArea::vertical() + // .stick_to_bottom(true) + // .show(ui, |ui| { + // for line in &state.nmea_log { + // ui.monospace(line); + // } + // }); + // }); + + // Write to console + for line in &state.nmea_log { + println!("{line}"); + } // ===================================================================== // Mini floating sky map // ===================================================================== - egui::Area::new("mini_sky_map".into()) - .anchor(egui::Align2::RIGHT_TOP, [-10.0, 10.0]) - .show(ctx, |ui| { - self.draw_satellite_map(ui, &state.satellites); - }); + // egui::Area::new("mini_sky_map".into()) + // .anchor(egui::Align2::RIGHT_TOP, [-10.0, 10.0]) + // .show(ctx, |ui| { + // self.draw_satellite_map(ui, &state.satellites); + // }); } } -- 2.39.5 From 88f39df488fa99f8c201276dfed32486478bd424 Mon Sep 17 00:00:00 2001 From: mattbk Date: Mon, 7 Sep 2026 10:40:40 -0500 Subject: [PATCH 2/5] Rip out the GUI, run forever, log to terminal. --- src/main.rs | 262 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 178 insertions(+), 84 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2f0d55e..df54179 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,7 +47,7 @@ impl Default for MyApp { // ===================================================================== // Satellite Map Drawing Method // ===================================================================== -impl MyApp { +// impl MyApp { // fn draw_satellite_map(&self, ui: &mut egui::Ui, sats: &[Satellite]) { // Plot::new("satellite_map") // .width(300.0) @@ -78,97 +78,101 @@ impl MyApp { // } // }); // } -} +// } // ===================================================================== // Main App UI // ===================================================================== -impl eframe::App for MyApp { - fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - let mut state = self.state.lock().unwrap(); +// impl eframe::App for MyApp { + // fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { + // let mut state = self.state.lock().unwrap(); - // Main panel - // egui::CentralPanel::default().show(ctx, |ui| { - // ui.heading("Select COM Port"); + // // Main panel + // // egui::CentralPanel::default().show(ctx, |ui| { + // // ui.heading("Select COM Port"); - // let ports = state.ports.clone(); + // // let ports = state.ports.clone(); - // egui::ComboBox::from_label("COM Port") - // .selected_text(state.selected_port.as_deref().unwrap_or("Select a Port")) - // .show_ui(ui, |cb| { - // for port in ports { - // cb.selectable_value( - // &mut state.selected_port, - // Some(port.clone()), - // port, - // ); - // } - // }); + // // egui::ComboBox::from_label("COM Port") + // // .selected_text(state.selected_port.as_deref().unwrap_or("Select a Port")) + // // .show_ui(ui, |cb| { + // // for port in ports { + // // cb.selectable_value( + // // &mut state.selected_port, + // // Some(port.clone()), + // // port, + // // ); + // // } + // // }); - // if ui.button("Start Reading").clicked() && !state.is_reading { - // if let Some(port_name) = state.selected_port.clone() { - let state_clone = Arc::clone(&self.state); + // // if ui.button("Start Reading").clicked() && !state.is_reading { + // // if let Some(port_name) = state.selected_port.clone() { + // // let state_clone = Arc::clone(&self.state); - let port_name = "/dev/tty.usbmodem1301"; + // // Harcode port for dev + // let port_name = "/dev/tty.usbmodem1301"; - // Thread for GPS streaming - thread::spawn(move || { - let port = serialport::new(port_name, 9600) - .timeout(Duration::from_millis(1000)) - .open(); + // // Thread for GPS streaming + // thread::spawn(move || { + // let port = serialport::new(port_name, 9600) + // .timeout(Duration::from_millis(1000)) + // .open(); - if let Ok(mut serial) = port { - let mut buf = [0u8; 1024]; + // if let Ok(mut serial) = port { + // let mut buf = [0u8; 1024]; - loop { - match serial.read(&mut buf) { - Ok(n) => { - let data = String::from_utf8_lossy(&buf[..n]); - // let mut satellites = Vec::new(); + // loop { + // match serial.read(&mut buf) { + // Ok(n) => { + // let data = String::from_utf8_lossy(&buf[..n]); + // // let mut satellites = Vec::new(); - for line in data.lines() { + // for line in data.lines() { + // println!("{}", line.to_string()); - // 🔵 Append NMEA line to log - { - let mut st = state_clone.lock().unwrap(); - st.nmea_log.push(line.to_string()); - // Keep log trimmed - if st.nmea_log.len() > 500 { - st.nmea_log.remove(0); - } - } + // // 🔵 Append NMEA line to log + // // { + // // let mut st = state_clone.lock().unwrap(); + // // st.nmea_log.push(line.to_string()); - // Parse GSV - if line.starts_with("$GPGSV") { - //let fields: Vec<&str> = line.split(',').collect(); - //let mut i = 4; + // // // Keep log trimmed + // // if st.nmea_log.len() > 500 { + // // st.nmea_log.remove(0); + // // } + // // } - // while i + 3 < fields.len() { - // satellites.push(Satellite { - // id: fields[i].to_string(), - // latitude: fields[i + 1].parse().unwrap_or(0.0), - // longitude: fields[i + 2].parse().unwrap_or(0.0), - // strength: fields[i + 3].parse().unwrap_or(0), - // }); - // i += 4; - // } - } - } - // Update satellites - //let mut st = state_clone.lock().unwrap(); - // st.satellites = satellites; - } - Err(_) => break, - } + // // Parse GSV + // // if line.starts_with("$GPGSV") { + // //let fields: Vec<&str> = line.split(',').collect(); + // //let mut i = 4; - thread::sleep(Duration::from_millis(200)); - } - } - }); + // // while i + 3 < fields.len() { + // // satellites.push(Satellite { + // // id: fields[i].to_string(), + // // latitude: fields[i + 1].parse().unwrap_or(0.0), + // // longitude: fields[i + 2].parse().unwrap_or(0.0), + // // strength: fields[i + 3].parse().unwrap_or(0), + // // }); + // // i += 4; + // // } + // // } + // } - state.is_reading = true; + // // Update satellites + // //let mut st = state_clone.lock().unwrap(); + // // st.satellites = satellites; + // } + // Err(_) => break, + // } + + // thread::sleep(Duration::from_millis(200)); + // } + // } + // }); + + // state.is_reading = true; // } // } @@ -207,9 +211,10 @@ impl eframe::App for MyApp { // }); // Write to console - for line in &state.nmea_log { - println!("{line}"); - } + // for line in &state.nmea_log { + // println!("{line}"); + // } + // ===================================================================== // Mini floating sky map @@ -219,18 +224,107 @@ impl eframe::App for MyApp { // .show(ctx, |ui| { // self.draw_satellite_map(ui, &state.satellites); // }); - } -} +// } +// } // ===================================================================== // Run // ===================================================================== -fn main() -> eframe::Result<()> { - let options = eframe::NativeOptions::default(); +fn main() { + // let options = eframe::NativeOptions::default(); + + while 1 == 1 { + + // Main panel + // egui::CentralPanel::default().show(ctx, |ui| { + // ui.heading("Select COM Port"); + + // let ports = state.ports.clone(); + + // egui::ComboBox::from_label("COM Port") + // .selected_text(state.selected_port.as_deref().unwrap_or("Select a Port")) + // .show_ui(ui, |cb| { + // for port in ports { + // cb.selectable_value( + // &mut state.selected_port, + // Some(port.clone()), + // port, + // ); + // } + // }); + + // if ui.button("Start Reading").clicked() && !state.is_reading { + // if let Some(port_name) = state.selected_port.clone() { + // let state_clone = Arc::clone(&self.state); + + // Harcode port for dev + let port_name = "/dev/tty.usbmodem1301"; + + // Thread for GPS streaming + thread::spawn(move || { + let port = serialport::new(port_name, 9600) + .timeout(Duration::from_millis(1000)) + .open(); + + if let Ok(mut serial) = port { + let mut buf = [0u8; 1024]; + + loop { + match serial.read(&mut buf) { + Ok(n) => { + let data = String::from_utf8_lossy(&buf[..n]); + // let mut satellites = Vec::new(); + + for line in data.lines() { + println!("{}", line.to_string()); + + + // 🔵 Append NMEA line to log + // { + // let mut st = state_clone.lock().unwrap(); + // st.nmea_log.push(line.to_string()); + + // // Keep log trimmed + // if st.nmea_log.len() > 500 { + // st.nmea_log.remove(0); + // } + // } + + + // Parse GSV + // if line.starts_with("$GPGSV") { + //let fields: Vec<&str> = line.split(',').collect(); + //let mut i = 4; + + // while i + 3 < fields.len() { + // satellites.push(Satellite { + // id: fields[i].to_string(), + // latitude: fields[i + 1].parse().unwrap_or(0.0), + // longitude: fields[i + 2].parse().unwrap_or(0.0), + // strength: fields[i + 3].parse().unwrap_or(0), + // }); + // i += 4; + // } + // } + } + + // Update satellites + //let mut st = state_clone.lock().unwrap(); + // st.satellites = satellites; + } + Err(_) => break, + } + + thread::sleep(Duration::from_millis(200)); + } + } + }); + + // eframe::run_native( + // "NMEA GPS Viewer", + // options, + // Box::new(|_cc| Box::new(MyApp::default())), + // ) + } - eframe::run_native( - "NMEA GPS Viewer", - options, - Box::new(|_cc| Box::new(MyApp::default())), - ) } -- 2.39.5 From eb37737bda3c3e1e220c3faff5ee1ad01952f1fa Mon Sep 17 00:00:00 2001 From: mattbk Date: Mon, 7 Sep 2026 12:51:32 -0500 Subject: [PATCH 3/5] Write lat/lon to terminal. --- Cargo.toml | 6 +- src/main.rs | 362 ++++++++-------------------------------------------- 2 files changed, 53 insertions(+), 315 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8966f60..ac56ce6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,8 +4,6 @@ version = "0.1.0" edition = "2021" [dependencies] -eframe = { version = "0.27", features = ["wgpu", "persistence"] } -egui = "0.27" -egui_plot = "0.27" serialport = "4.2" -nmea = "0.6" +nmea = {version = "0.6", features = ["GGA"]} + diff --git a/src/main.rs b/src/main.rs index df54179..ad77bb0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,330 +1,70 @@ -use eframe::egui; -//use serialport::available_ports; -use std::sync::{Arc, Mutex}; +use nmea::Nmea; +use nmea::SentenceType; use std::thread; use std::time::Duration; -// use egui_plot::{Plot, PlotPoints, Points, Text, Line}; - -#[derive(Default, Clone)] -// struct Satellite { -// id: String, -// latitude: f64, -// longitude: f64, -// strength: u8, -// } - -//#[derive(Default)] -struct AppState { - //ports: Vec, - //selected_port: Option, - //satellites: Vec, - is_reading: bool, - - // 🔵 NEW: live NMEA data buffer - nmea_log: Vec, -} - -pub struct MyApp { - state: Arc>, -} - -impl Default for MyApp { - fn default() -> Self { - // let ports = available_ports() - // .map(|ps| ps.into_iter().map(|p| p.port_name).collect()) - // .unwrap_or_default(); - - Self { - state: Arc::new(Mutex::new(AppState { - //ports, - ..Default::default() - })), - } - } -} - -// ===================================================================== -// Satellite Map Drawing Method -// ===================================================================== -// impl MyApp { - // fn draw_satellite_map(&self, ui: &mut egui::Ui, sats: &[Satellite]) { - // Plot::new("satellite_map") - // .width(300.0) - // .height(300.0) - // .view_aspect(1.0) - // .show(ui, |plot_ui| { - // // Draw outline circle - // let circle: PlotPoints = (0..360) - // .map(|deg| { - // let rad = (deg as f64).to_radians(); - // [rad.cos(), rad.sin()] - // }) - // .collect::>() - // .into(); - - // plot_ui.line(Line::new(circle)); - - // // Draw satellites - // for sat in sats { - // let az = sat.longitude.to_radians(); - // let el = sat.latitude.to_radians(); - - // let x = el.cos() * az.cos(); - // let y = el.cos() * az.sin(); - - // plot_ui.points(Points::new(vec![[x, y]]).radius(3.0)); - // plot_ui.text(Text::new([x, y].into(), sat.id.clone())); - // } - // }); - // } -// } - -// ===================================================================== -// Main App UI -// ===================================================================== -// impl eframe::App for MyApp { - // fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - // let mut state = self.state.lock().unwrap(); - - // // Main panel - // // egui::CentralPanel::default().show(ctx, |ui| { - // // ui.heading("Select COM Port"); - - // // let ports = state.ports.clone(); - - // // egui::ComboBox::from_label("COM Port") - // // .selected_text(state.selected_port.as_deref().unwrap_or("Select a Port")) - // // .show_ui(ui, |cb| { - // // for port in ports { - // // cb.selectable_value( - // // &mut state.selected_port, - // // Some(port.clone()), - // // port, - // // ); - // // } - // // }); - - // // if ui.button("Start Reading").clicked() && !state.is_reading { - // // if let Some(port_name) = state.selected_port.clone() { - // // let state_clone = Arc::clone(&self.state); - - // // Harcode port for dev - // let port_name = "/dev/tty.usbmodem1301"; - - // // Thread for GPS streaming - // thread::spawn(move || { - // let port = serialport::new(port_name, 9600) - // .timeout(Duration::from_millis(1000)) - // .open(); - - // if let Ok(mut serial) = port { - // let mut buf = [0u8; 1024]; - - // loop { - // match serial.read(&mut buf) { - // Ok(n) => { - // let data = String::from_utf8_lossy(&buf[..n]); - // // let mut satellites = Vec::new(); - - // for line in data.lines() { - // println!("{}", line.to_string()); - - - // // 🔵 Append NMEA line to log - // // { - // // let mut st = state_clone.lock().unwrap(); - // // st.nmea_log.push(line.to_string()); - - // // // Keep log trimmed - // // if st.nmea_log.len() > 500 { - // // st.nmea_log.remove(0); - // // } - // // } - - - // // Parse GSV - // // if line.starts_with("$GPGSV") { - // //let fields: Vec<&str> = line.split(',').collect(); - // //let mut i = 4; - - // // while i + 3 < fields.len() { - // // satellites.push(Satellite { - // // id: fields[i].to_string(), - // // latitude: fields[i + 1].parse().unwrap_or(0.0), - // // longitude: fields[i + 2].parse().unwrap_or(0.0), - // // strength: fields[i + 3].parse().unwrap_or(0), - // // }); - // // i += 4; - // // } - // // } - // } - - // // Update satellites - // //let mut st = state_clone.lock().unwrap(); - // // st.satellites = satellites; - // } - // Err(_) => break, - // } - - // thread::sleep(Duration::from_millis(200)); - // } - // } - // }); - - // state.is_reading = true; - // } - // } - - // ui.separator(); - // ui.heading("Satellites"); - - // egui::ScrollArea::vertical().show(ui, |ui| { - // for sat in &state.satellites { - // ui.horizontal(|ui| { - // ui.label(format!("ID: {}", sat.id)); - // ui.label(format!("Elv: {:.2}", sat.latitude)); - // ui.label(format!("Azm: {:.2}", sat.longitude)); - // ui.label(format!("Strength: {}", sat.strength)); - // }); - // } - // }); - // }); - - // ===================================================================== - // NEW: Live GPS Stream Window - // ===================================================================== - // egui::Window::new("GPS Stream") - // .default_width(400.0) - // .default_height(300.0) - // .resizable(true) - // .show(ctx, |ui| { - // ui.label("Live NMEA Data:"); - - // egui::ScrollArea::vertical() - // .stick_to_bottom(true) - // .show(ui, |ui| { - // for line in &state.nmea_log { - // ui.monospace(line); - // } - // }); - // }); - - // Write to console - // for line in &state.nmea_log { - // println!("{line}"); - // } - - - // ===================================================================== - // Mini floating sky map - // ===================================================================== - // egui::Area::new("mini_sky_map".into()) - // .anchor(egui::Align2::RIGHT_TOP, [-10.0, 10.0]) - // .show(ctx, |ui| { - // self.draw_satellite_map(ui, &state.satellites); - // }); -// } -// } - -// ===================================================================== -// Run -// ===================================================================== fn main() { - // let options = eframe::NativeOptions::default(); - + // Inifnite loop until I add controls while 1 == 1 { + let mut nmea = Nmea::default(); - // Main panel - // egui::CentralPanel::default().show(ctx, |ui| { - // ui.heading("Select COM Port"); + // Harcode port for dev + let port_name = "/dev/tty.usbmodem1301"; - // let ports = state.ports.clone(); + // Thread for GPS streaming + thread::spawn(move || { + let port = serialport::new(port_name, 9600) + .timeout(Duration::from_millis(1000)) + .open(); - // egui::ComboBox::from_label("COM Port") - // .selected_text(state.selected_port.as_deref().unwrap_or("Select a Port")) - // .show_ui(ui, |cb| { - // for port in ports { - // cb.selectable_value( - // &mut state.selected_port, - // Some(port.clone()), - // port, - // ); - // } - // }); + if let Ok(mut serial) = port { + let mut buf = [0u8; 1024]; - // if ui.button("Start Reading").clicked() && !state.is_reading { - // if let Some(port_name) = state.selected_port.clone() { - // let state_clone = Arc::clone(&self.state); + loop { + match serial.read(&mut buf) { + Ok(n) => { + let data = String::from_utf8_lossy(&buf[..n]); - // Harcode port for dev - let port_name = "/dev/tty.usbmodem1301"; + for line in data.lines() { + //println!("{}", line.to_string()); - // Thread for GPS streaming - thread::spawn(move || { - let port = serialport::new(port_name, 9600) - .timeout(Duration::from_millis(1000)) - .open(); - - if let Ok(mut serial) = port { - let mut buf = [0u8; 1024]; - - loop { - match serial.read(&mut buf) { - Ok(n) => { - let data = String::from_utf8_lossy(&buf[..n]); - // let mut satellites = Vec::new(); - - for line in data.lines() { - println!("{}", line.to_string()); - - - // 🔵 Append NMEA line to log - // { - // let mut st = state_clone.lock().unwrap(); - // st.nmea_log.push(line.to_string()); - - // // Keep log trimmed - // if st.nmea_log.len() > 500 { - // st.nmea_log.remove(0); - // } - // } - - - // Parse GSV - // if line.starts_with("$GPGSV") { - //let fields: Vec<&str> = line.split(',').collect(); - //let mut i = 4; - - // while i + 3 < fields.len() { - // satellites.push(Satellite { - // id: fields[i].to_string(), - // latitude: fields[i + 1].parse().unwrap_or(0.0), - // longitude: fields[i + 2].parse().unwrap_or(0.0), - // strength: fields[i + 3].parse().unwrap_or(0), - // }); - // i += 4; - // } - // } - } - - // Update satellites - //let mut st = state_clone.lock().unwrap(); - // st.satellites = satellites; + // Check sentence type + let sentence_type = match nmea.parse(line) { + Ok(sentence_type) => sentence_type, + Err(_) => { + return; } - Err(_) => break, + }; + + // Only keep the GLL sentences + if sentence_type == SentenceType::GLL { + //nmea.parse(line).unwrap(); + //println!("{:?}", nmea.latitude); + // if let Some(nmea.latitude) = x { + // println!("Matched {:?}!", x); + let lat = match nmea.latitude { + Some(lat) => lat, + None => todo!() + } ; + let lon = match nmea.longitude { + Some(lon) => lon, + None => todo!() + } ; + println!("{lat}, {lon}"); + // } } - thread::sleep(Duration::from_millis(200)); + + + } } - }); + Err(_) => break, + } - // eframe::run_native( - // "NMEA GPS Viewer", - // options, - // Box::new(|_cc| Box::new(MyApp::default())), - // ) + thread::sleep(Duration::from_millis(200)); } - + } + }); + } } -- 2.39.5 From 8b2804fe1f431ffbbc4fdde1941ce7223392131b Mon Sep 17 00:00:00 2001 From: mattbk Date: Mon, 7 Sep 2026 15:02:13 -0500 Subject: [PATCH 4/5] Show datetime; take port from an argument. --- Cargo.toml | 4 +++- src/main.rs | 49 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ac56ce6..c2f5cdd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,11 @@ [package] -name = "RUST_NMEA_PARSER" +name = "gpsll" version = "0.1.0" edition = "2021" [dependencies] serialport = "4.2" nmea = {version = "0.6", features = ["GGA"]} +clap = { version = "4", features = ["derive"] } +chrono = "0.4.45" diff --git a/src/main.rs b/src/main.rs index ad77bb0..e157233 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,14 +2,46 @@ use nmea::Nmea; use nmea::SentenceType; use std::thread; use std::time::Duration; +use clap::Parser; +use chrono::Local; + +/// Command-line arguments using Clap. +#[derive(Parser, Debug)] +#[command(author, version, about = "A tool for echoing latitude and longitude from a GPS USB dongle..")] +struct Cli { + + /// COM port + #[arg(short = 'c', long)] + com: Option, +} fn main() { + + let cli = Cli::parse(); + + + + let com = match cli.com { + Some(com) => com, + None => { + let ports = serialport::available_ports().expect("No ports found!"); + println!("Avaiable Ports:"); + for p in ports { + println!("{}", p.port_name); + } + println!("\nMissing `-c` port argument, use one listed above."); + return; + } //todo!() + } ; + println!("Reading from {com:?}"); + // Inifnite loop until I add controls while 1 == 1 { let mut nmea = Nmea::default(); // Harcode port for dev - let port_name = "/dev/tty.usbmodem1301"; + //let port_name = "/dev/tty.usbmodem1301"; + let port_name = com.clone(); // Thread for GPS streaming thread::spawn(move || { @@ -26,7 +58,6 @@ fn main() { let data = String::from_utf8_lossy(&buf[..n]); for line in data.lines() { - //println!("{}", line.to_string()); // Check sentence type let sentence_type = match nmea.parse(line) { @@ -38,10 +69,6 @@ fn main() { // Only keep the GLL sentences if sentence_type == SentenceType::GLL { - //nmea.parse(line).unwrap(); - //println!("{:?}", nmea.latitude); - // if let Some(nmea.latitude) = x { - // println!("Matched {:?}!", x); let lat = match nmea.latitude { Some(lat) => lat, None => todo!() @@ -50,19 +77,15 @@ fn main() { Some(lon) => lon, None => todo!() } ; - println!("{lat}, {lon}"); - // } + let date = Local::now(); + println!("{}, {lat}, {lon}", date.format("%Y-%m-%d %H:%M:%S")); + } - - - - } } Err(_) => break, } - thread::sleep(Duration::from_millis(200)); } } }); -- 2.39.5 From 24100ffb2646375c3d235e9cf2d8193875210ef0 Mon Sep 17 00:00:00 2001 From: mattbk Date: Mon, 7 Sep 2026 15:06:01 -0500 Subject: [PATCH 5/5] Fix typos. --- src/main.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index e157233..33e09ab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use chrono::Local; /// Command-line arguments using Clap. #[derive(Parser, Debug)] -#[command(author, version, about = "A tool for echoing latitude and longitude from a GPS USB dongle..")] +#[command(author, version, about = "A tool for echoing latitude and longitude from a GPS USB dongle.")] struct Cli { /// COM port @@ -19,13 +19,12 @@ fn main() { let cli = Cli::parse(); - - let com = match cli.com { Some(com) => com, None => { + // https://github.com/serialport/serialport-rs#listing-available-ports let ports = serialport::available_ports().expect("No ports found!"); - println!("Avaiable Ports:"); + println!("Available Ports:"); for p in ports { println!("{}", p.port_name); } -- 2.39.5