From 52a829a9a8d9e67f93d8e142072e5ca21204d0d5 Mon Sep 17 00:00:00 2001 From: mattbk Date: Fri, 11 Sep 2026 18:49:32 -0500 Subject: [PATCH] Bring in location! Closes #2. --- Cargo.lock | 182 +++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + src/main.rs | 106 +++++++++++++++++++++++++++--- 3 files changed, 280 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a52337a..7423de4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -94,6 +94,7 @@ dependencies = [ "csv", "io", "iter", + "nmea", "serialport", ] @@ -103,6 +104,12 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bitflags" version = "1.3.2" @@ -202,6 +209,7 @@ dependencies = [ "iana-time-zone", "js-sys", "num-traits", + "serde", "wasm-bindgen", "windows-link", ] @@ -376,6 +384,15 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "serde_core", +] + [[package]] name = "derive_more" version = "0.99.20" @@ -702,6 +719,21 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.5" @@ -718,6 +750,16 @@ version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +[[package]] +name = "heapless" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ba4bd83f9415b58b4ed8dc5714c76e626a105be4646c02630ad730ad3b5aa4" +dependencies = [ + "hash32", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.5.0" @@ -780,6 +822,17 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + [[package]] name = "indexmap" version = "2.14.2" @@ -788,6 +841,8 @@ checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" dependencies = [ "equivalent", "hashbrown 0.17.1", + "serde", + "serde_core", ] [[package]] @@ -871,6 +926,12 @@ dependencies = [ "libc", ] +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + [[package]] name = "libudev" version = "0.3.0" @@ -923,6 +984,37 @@ dependencies = [ "libc", ] +[[package]] +name = "nmea" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f194698caba0a523ca095ecb0d5b8a9a87f45be75f89d0a30bccb1ba1e142159" +dependencies = [ + "arrayvec", + "cfg-if", + "chrono", + "heapless", + "nom", + "num-traits", + "serde", + "serde_with", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + [[package]] name = "num-traits" version = "0.2.19" @@ -930,6 +1022,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -998,6 +1091,12 @@ version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "primitive-types" version = "0.12.2" @@ -1184,6 +1283,15 @@ version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", +] + [[package]] name = "serde_core" version = "1.0.229" @@ -1204,6 +1312,36 @@ dependencies = [ "syn 3.0.5", ] +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_with" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.14.2", + "serde", + "serde_derive", + "serde_json", + "time", +] + [[package]] name = "serialport" version = "4.10.0" @@ -1241,6 +1379,12 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9be42f50aa861c555654aa3a37f52f4b1074bacf4e48fe0ef7fa584e80f1f0f" +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + [[package]] name = "static_assertions" version = "1.1.0" @@ -1307,6 +1451,36 @@ dependencies = [ "syn 3.0.5", ] +[[package]] +name = "time" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "time-macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "toml_datetime" version = "1.1.1+spec-1.1.0" @@ -1322,7 +1496,7 @@ version = "0.25.13+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" dependencies = [ - "indexmap", + "indexmap 2.14.2", "toml_datetime", "toml_parser", "winnow", @@ -1648,3 +1822,9 @@ dependencies = [ "quote", "syn 2.0.119", ] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/Cargo.toml b/Cargo.toml index 315a131..7131809 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,5 +9,6 @@ clap = { version = "4", features = ["derive"] } csv = "1.4.0" io = "0.0.2" iter = "0.1.0" +nmea = "0.8.0" serialport = "4.10.0" diff --git a/src/main.rs b/src/main.rs index 13fd5f3..5f3e233 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,7 @@ use chrono::Local; use clap::Parser; +use nmea::Nmea; +use nmea::SentenceType; use serialport::DataBits; use serialport::Parity; use serialport::StopBits; @@ -14,12 +16,16 @@ use std::time::Duration; #[derive(Parser, Debug)] #[command(author, version, about = "ASMR: Automatic S-Meter Reader")] struct Cli { - /// COM port + /// Rig COM port #[arg(short = 'c', long)] com: Option, + /// GPS COM port + #[arg(short = 'g', long)] + gps: Option, + /// Format - #[arg(short = 'o', long,)] + #[arg(short = 'o', long)] file: Option, /// Frequency @@ -31,6 +37,73 @@ struct Cli { wait: Option, } +// Get location +// Mofified from https://amiok.net/gitea/W1CDN/gpsll +fn get_loc(port: String) -> [f64; 2] { + let mut nmea = Nmea::default(); + + // Harcode port for dev + //let port_name = "/dev/tty.usbmodem1301"; + let port_name = port; + + //fn read_loc(com: &str) -> &str { + //println!("Reading from {port_name}"); + + 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]); + + for line in data.lines() { + // Check sentence type + let sentence_type = match nmea.parse(line) { + Ok(sentence_type) => sentence_type, + Err(_) => { + break; + } + }; + + // Only keep the GLL sentences + if sentence_type == SentenceType::GLL { + let lat = match nmea.latitude { + Some(lat) => lat, + None => -9999.25, + }; + let lon = match nmea.longitude { + Some(lon) => lon, + None => -9999.25, + }; + //let date = Local::now(); + //println!("{}, {lat}, {lon}", date.format("%Y-%m-%d %H:%M:%S")); + return [lat, lon]; + //"{},{:.8},{:.8}", + //date.format("%Y-%m-%d %H:%M:%S"), + //"{:.8},{:.8}", + } + } + } + Err(_) => {} // lol that I can just not put a return in? + } + } + } else { + // https://github.com/serialport/serialport-rs#listing-available-ports + let ports = serialport::available_ports().expect("No ports found!"); + println!("Available Ports:"); + for p in ports { + println!("{}", p.port_name); + } + + return [-9999.25, -9999.25]; //format!("\nCould not connect to GPS port. Is it listed above?"); + } +} + // Read S-meter fn get_smeter(comport: &str) -> String { let mut port = serialport::new(comport, 4800) @@ -153,7 +226,21 @@ fn main() { for p in ports { println!("{}", p.port_name); } - println!("\nMissing `-c` port argument, use one listed above."); + println!("\nMissing `-c` rig port argument, use one listed above."); + return; + } //todo!() + }; + + let gps = match cli.gps { + Some(gps) => gps, + None => { + // https://github.com/serialport/serialport-rs#listing-available-ports + let ports = serialport::available_ports().expect("No ports found!"); + println!("Available Ports:"); + for p in ports { + println!("{}", p.port_name); + } + println!("\nMissing `-g` GPS port argument, use one listed above."); return; } //todo!() }; @@ -162,7 +249,7 @@ fn main() { Some(file_out) => { println!("Saving results to {}", file_out); file_out - }, + } None => { println!("Not saving results. Use `-o file.csv` to save to a file."); "no file".to_string() @@ -191,6 +278,8 @@ fn main() { // Simple test loop to make sure we are getting values each time //for _i in 1..11 { loop { + // Get location + let ll = get_loc(gps.clone()); // Get datestamp let date = Local::now(); // Get S-meter @@ -211,9 +300,10 @@ fn main() { if let Err(err) = write_row( [ date.format("%Y-%m-%d %H:%M:%S").to_string(), - frequency.to_string(), - "lat".to_string(), - "lon".to_string(), + //frequency.to_string(), + format!("{:09}", frequency), + format!("{:.8}", ll[0]), + format!("{:.8}", ll[1]), s_val.to_string(), ], &file_out, @@ -222,6 +312,6 @@ fn main() { println!("{}", err); } } - sleep(Duration::from_millis(wait as u64 * 1000)); + sleep(Duration::from_millis((wait as u64 * 1000) - 1000)); } }