Skip to content

Commit bfe149a

Browse files
committed
Refactoring / removed unneeded gps parse sentences for current implementation
1 parent 4a1d1f1 commit bfe149a

File tree

5 files changed

+148
-56
lines changed

5 files changed

+148
-56
lines changed

Cargo.lock

+37-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ serialport = "4.3.0"
88
config = "0.13.4"
99
paho-mqtt = "0.12.3"
1010
futures = "0.3.30"
11-
lazy_static = "1.4.0"
11+
lazy_static = "1.4.0"
12+
gumdrop = "0.8.1"

src/config.rs

+52-35
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use config::Config;
1+
use config::{Config, File};
2+
use std::path::Path;
23

34
/// Struct to hold the application configuration.
45
pub struct AppConfig {
@@ -8,7 +9,7 @@ pub struct AppConfig {
89
/// The baud rate for the serial port.
910
pub baud_rate: i64,
1011

11-
//Should the GPS sample rate be increased to 10Hz
12+
// Should the GPS sample rate be increased to 10Hz
1213
pub set_gps_to_10hz: bool,
1314

1415
/// The MQTT broker host address.
@@ -17,46 +18,62 @@ pub struct AppConfig {
1718
/// The MQTT broker port number.
1819
pub mqtt_port: i64,
1920

20-
//The base topic of MQTT where data is pushed
21+
// The base topic of MQTT where data is pushed
2122
pub mqtt_base_topic: String,
23+
24+
// Optional: Path to the configuration file
25+
pub config_path: Option<String>,
2226
}
2327

2428
/// Load application configuration from a TOML file.
2529
///
26-
/// This function reads the configuration settings from a TOML file named "settings.toml".
27-
/// It expects the following keys in the TOML file: "port_name", "baud_rate", "mqtt_host", and "mqtt_port".
30+
/// This function reads the configuration settings from a TOML file.
2831
///
29-
/// # Panics
30-
/// Panics if any of the required configuration keys are missing or if there is an error reading the configuration file.
32+
/// # Arguments
33+
/// - `config_path`: An optional path to the configuration file.
3134
///
3235
/// # Returns
33-
/// Returns an `AppConfig` struct containing the loaded configuration.
34-
pub fn load_configuration() -> AppConfig {
35-
// Build a new Config object with a file source.
36-
let settings = Config::builder()
37-
.add_source(config::File::with_name("settings.toml"))
38-
.build()
39-
.unwrap();
36+
/// Returns a `Result` containing either the `AppConfig` struct with the loaded configuration or an error message.
37+
pub fn load_configuration(config_path: Option<&str>) -> Result<AppConfig, String> {
38+
// Create a default configuration
39+
let mut settings = Config::default();
4040

41-
// Create an AppConfig struct by extracting values from the configuration.
42-
AppConfig {
43-
port_name: settings
44-
.get_string("port_name")
45-
.expect("Missing port_name in configuration"),
46-
baud_rate: settings
47-
.get_int("baud_rate")
48-
.expect("Missing baud_rate in configuration"),
49-
set_gps_to_10hz: settings
50-
.get_bool("set_gps_to_10hz")
51-
.expect("Missing set_gps_to_10hz in configuration"),
52-
mqtt_host: settings
53-
.get_string("mqtt_host")
54-
.expect("Missing mqtt_host in configuration"),
55-
mqtt_port: settings
56-
.get_int("mqtt_port")
57-
.expect("Missing mqtt_port in configuration"),
58-
mqtt_base_topic: settings
59-
.get_string("mqtt_base_topic")
60-
.expect("Missing mqtt_base_topic in configuration"),
41+
// Try to load from the passed config_path
42+
if let Some(path) = config_path {
43+
match Config::builder().add_source(File::with_name(path)).build() {
44+
Ok(config) => settings = config,
45+
Err(err) => return Err(format!("{}", err)),
46+
}
47+
} else {
48+
// Try to load from the executable's directory
49+
if let Ok(exe_dir) = std::env::current_exe() {
50+
let exe_dir = exe_dir.parent().unwrap_or_else(|| Path::new("."));
51+
let default_path = exe_dir.join("settings.toml");
52+
53+
if let Ok(config) =
54+
Config::builder().add_source(File::with_name(default_path.to_str().unwrap())).build()
55+
{
56+
settings = config;
57+
}
58+
}
59+
60+
// Try to load from /etc/g86-car-telemetry/speeduino-to-mqtt.toml
61+
if let Ok(config) = Config::builder()
62+
.add_source(File::with_name("/usr/etc/g86-car-telemetry/gps-to-mqtt.toml"))
63+
.build()
64+
{
65+
settings = config;
66+
}
6167
}
62-
}
68+
69+
// Create an AppConfig struct by extracting values from the configuration.
70+
Ok(AppConfig {
71+
port_name: settings.get_string("port_name").unwrap_or_else(|_| "default_port".to_string()),
72+
baud_rate: settings.get_int("baud_rate").unwrap_or(9600),
73+
set_gps_to_10hz: settings.get_bool("set_gps_to_10hz").unwrap_or(false),
74+
mqtt_host: settings.get_string("mqtt_host").unwrap_or_else(|_| "default_host".to_string()),
75+
mqtt_port: settings.get_int("mqtt_port").unwrap_or(1883),
76+
mqtt_base_topic: settings.get_string("mqtt_base_topic").unwrap_or_else(|_| "default_topic".to_string()),
77+
config_path: config_path.map(|p| p.to_string()),
78+
})
79+
}

src/main.rs

+46-9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
mod config;
2+
mod gps_data_parser;
3+
mod mqtt_handler;
4+
mod serial_port_handler;
5+
6+
use serial_port_handler::{read_from_port, setup_serial_port};
7+
use gumdrop::Options;
8+
use config::load_configuration;
9+
110
/// # GPS Data Processor
211
///
312
/// This Rust application serves as a processor for GPS data, converting it to MQTT messages.
@@ -19,13 +28,6 @@
1928
///
2029
/// - `main()`: The main function that loads configuration, sets up serial communication, and starts reading data from the port.
2130
/// - `display_welcome()`: Function to display a graphical welcome message.
22-
mod config;
23-
mod gps_data_parser;
24-
mod mqtt_handler;
25-
mod serial_port_handler;
26-
27-
use config::load_configuration;
28-
use serial_port_handler::{read_from_port, setup_serial_port};
2931
3032
/// Displays a graphical welcome message.
3133
fn display_welcome() {
@@ -35,12 +37,47 @@ fn display_welcome() {
3537
println!("==========================================\n");
3638
}
3739

40+
/// Define options for the program.
41+
#[derive(Debug, Options)]
42+
struct MyOptions {
43+
#[options(help = "print help message")]
44+
help: bool,
45+
46+
#[options(help = "Sets a custom config file", meta = "FILE")]
47+
config: Option<String>,
48+
}
49+
50+
fn print_help() {
51+
println!("Usage: gps-to-mqtt [options]");
52+
println!("Options:");
53+
println!(" -h, --help Print this help message");
54+
println!(" -c, --config FILE Sets a custom config file path");
55+
}
56+
3857
fn main() {
58+
// Parse CLI arguments using gumdrop
59+
let opts = MyOptions::parse_args_default_or_exit();
60+
61+
if opts.help {
62+
// Use custom print_help function to display help and exit
63+
print_help();
64+
std::process::exit(0);
65+
}
66+
3967
// Display welcome message
4068
display_welcome();
4169

4270
// Load configuration, set up serial port, and start processing
43-
let config = load_configuration();
71+
let config_path = opts.config.as_deref();
72+
let config = match load_configuration(config_path) {
73+
Ok(config) => config,
74+
Err(err) => {
75+
// Handle the error gracefully, print a message, and exit
76+
eprintln!("Error loading configuration: {}", err);
77+
std::process::exit(1);
78+
}
79+
};
80+
4481
let mut port = setup_serial_port(&config);
4582
read_from_port(&mut port, &config);
46-
}
83+
}

src/serial_port_handler.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,26 @@ use std::thread;
2323
/// # Returns
2424
///
2525
/// Returns a boxed trait object representing the opened serial port.
26-
pub fn setup_serial_port(config: &AppConfig) -> Box<dyn SerialPort> {
27-
26+
pub fn setup_serial_port(config: &AppConfig) -> Box<dyn serialport::SerialPort> {
2827
// Opening and configuring the specified serial port.
2928
println!("Opening port: {}", config.port_name);
30-
let mut port = serialport::new(&config.port_name, config.baud_rate as u32)
29+
30+
let mut port = match serialport::new(&config.port_name, config.baud_rate as u32)
3131
.timeout(std::time::Duration::from_millis(1000))
3232
.open()
33-
.expect("Failed to open port");
33+
{
34+
Ok(p) => p,
35+
Err(err) => {
36+
eprintln!("Failed to open port: {}", err);
37+
std::process::exit(1);
38+
}
39+
};
3440

3541
if config.set_gps_to_10hz {
3642
println!("Setting GPS sample rate to 10Hz");
3743
gps_resolution_to_10hz(&mut port);
3844
}
45+
3946
port
4047
}
4148

@@ -111,8 +118,6 @@ pub fn gps_resolution_to_10hz(port: &mut Box<dyn SerialPort>) {
111118

112119
/// Check if the user wants to quit by entering 'q' + Enter.
113120
fn check_quit(sender: mpsc::Sender<String>) {
114-
// Create a buffer to read user input
115-
let mut input_buffer = String::new();
116121

117122
// Read input from the user asynchronously
118123
let stdin = io::stdin();

0 commit comments

Comments
 (0)