Skip to content

Commit 9da7719

Browse files
CLI args better UI behavior.
1 parent 3a002f1 commit 9da7719

File tree

18 files changed

+423
-163
lines changed

18 files changed

+423
-163
lines changed

console_backend/src/cli_options.rs

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,56 @@
11
use clap::Clap;
2-
use std::{ops, path::PathBuf};
2+
use std::{
3+
ops::{Deref, Not},
4+
path::PathBuf,
5+
str::FromStr,
6+
};
7+
use strum::VariantNames;
38

9+
use crate::common_constants::{SbpLogging, Tabs};
410
use crate::constants::{AVAILABLE_BAUDRATES, AVAILABLE_REFRESH_RATES};
5-
use crate::types::{CliTabs, FlowControl};
11+
use crate::types::FlowControl;
12+
13+
#[derive(Debug)]
14+
pub struct CliTabs(Tabs);
15+
16+
impl Deref for CliTabs {
17+
type Target = Tabs;
18+
19+
fn deref(&self) -> &Self::Target {
20+
&self.0
21+
}
22+
}
23+
24+
impl FromStr for CliTabs {
25+
type Err = String;
26+
27+
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
28+
Ok(CliTabs(Tabs::from_str(s).map_err(|_| {
29+
format!("Must choose from available tabs {:?}", Tabs::VARIANTS)
30+
})?))
31+
}
32+
}
33+
34+
#[derive(Debug)]
35+
pub struct CliSbpLogging(SbpLogging);
36+
37+
impl Deref for CliSbpLogging {
38+
type Target = SbpLogging;
39+
40+
fn deref(&self) -> &Self::Target {
41+
&self.0
42+
}
43+
}
44+
45+
impl FromStr for CliSbpLogging {
46+
type Err = String;
47+
48+
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
49+
Ok(CliSbpLogging(SbpLogging::from_str(s).map_err(|_| {
50+
format!("Must choose from available tabs {:?}", SbpLogging::VARIANTS)
51+
})?))
52+
}
53+
}
654

755
#[derive(Clap, Debug)]
856
#[clap(name = "swift_navigation_console", about = "Swift Navigation Console.")]
@@ -14,17 +62,34 @@ pub struct CliOptions {
1462
#[clap(long = "exit-after")]
1563
pub exit_after: bool,
1664

17-
// // Frontend Options
65+
/// Enable CSV logging.
66+
#[clap(long = "csv-log")]
67+
pub csv_log: bool,
68+
69+
/// Enable SBP-JSON or SBP logging.
70+
#[clap(long = "sbp-log")]
71+
pub sbp_log: Option<CliSbpLogging>,
72+
73+
/// Set log directory.
74+
#[clap(long = "log-dirname")]
75+
pub dirname: Option<String>,
76+
77+
// Frontend Options
1878
/// Don't use opengl in plots.
19-
#[clap(long = "no-opengl", parse(from_flag = ops::Not::not))]
79+
#[clap(long = "no-opengl", parse(from_flag = Not::not))]
2080
pub no_opengl: bool,
2181

22-
/// Don't use opengl in plots.
82+
/// Change the refresh rate of the plots.
2383
#[clap(long = "refresh-rate", validator(is_refresh_rate))]
2484
pub refresh_rate: Option<u8>,
2585

86+
/// Start console from specific tab.
2687
#[clap(long = "tab")]
2788
pub tab: Option<CliTabs>,
89+
90+
/// Show CSV logging button.
91+
#[clap(long = "show-csv-log")]
92+
pub show_csv_log: bool,
2893
}
2994

3095
impl CliOptions {

console_backend/src/common_constants.rs

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,38 @@ pub enum Tabs {
3434
ADVANCED,
3535
}
3636

37+
#[derive(Clone, Debug, Display, EnumString, EnumVariantNames, Eq, Hash, PartialEq)]
38+
pub enum SbpLogging {
39+
#[strum(serialize = "OFF")]
40+
OFF,
41+
#[strum(serialize = "SBP_JSON")]
42+
SBP_JSON,
43+
#[strum(serialize = "SBP")]
44+
SBP,
45+
}
46+
47+
#[derive(Clone, Debug, Display, EnumString, EnumVariantNames, Eq, Hash, PartialEq)]
48+
pub enum CsvLogging {
49+
#[strum(serialize = "OFF")]
50+
OFF,
51+
#[strum(serialize = "ON")]
52+
ON,
53+
}
54+
55+
#[derive(Clone, Debug, Display, EnumString, EnumVariantNames, Eq, Hash, PartialEq)]
56+
pub enum LogLevel {
57+
#[strum(serialize = "ERROR")]
58+
ERROR,
59+
#[strum(serialize = "WARNING")]
60+
WARNING,
61+
#[strum(serialize = "NOTICE")]
62+
NOTICE,
63+
#[strum(serialize = "INFO")]
64+
INFO,
65+
#[strum(serialize = "DEBUG")]
66+
DEBUG,
67+
}
68+
3769
#[derive(Clone, Debug, Display, EnumString, EnumVariantNames, Eq, Hash, PartialEq)]
3870
pub enum Keys {
3971
#[strum(serialize = "POINTS")]
@@ -78,8 +110,40 @@ pub enum Keys {
78110
WEEK,
79111
#[strum(serialize = "ROWS")]
80112
ROWS,
113+
#[strum(serialize = "PREVIOUS_HOSTS")]
114+
PREVIOUS_HOSTS,
115+
#[strum(serialize = "PREVIOUS_PORTS")]
116+
PREVIOUS_PORTS,
117+
#[strum(serialize = "PREVIOUS_FILES")]
118+
PREVIOUS_FILES,
81119
#[strum(serialize = "CONNECTED")]
82120
CONNECTED,
121+
#[strum(serialize = "PORT")]
122+
PORT,
123+
#[strum(serialize = "POS")]
124+
POS,
125+
#[strum(serialize = "RTK")]
126+
RTK,
127+
#[strum(serialize = "SATS")]
128+
SATS,
129+
#[strum(serialize = "CORR_AGE")]
130+
CORR_AGE,
131+
#[strum(serialize = "INS")]
132+
INS,
133+
#[strum(serialize = "DATA_RATE")]
134+
DATA_RATE,
135+
#[strum(serialize = "SOLID_CONNECTION")]
136+
SOLID_CONNECTION,
137+
#[strum(serialize = "PREVIOUS_FOLDERS")]
138+
PREVIOUS_FOLDERS,
139+
#[strum(serialize = "SBP_LOGGING")]
140+
SBP_LOGGING,
141+
#[strum(serialize = "CSV_LOGGING")]
142+
CSV_LOGGING,
143+
#[strum(serialize = "SBP_LOGGING_LABELS")]
144+
SBP_LOGGING_LABELS,
145+
#[strum(serialize = "LOG_LEVEL_LABELS")]
146+
LOG_LEVEL_LABELS,
83147
}
84148

85149
#[derive(Clone, Debug, Display, EnumString, EnumVariantNames, Eq, Hash, PartialEq)]
@@ -96,10 +160,10 @@ pub enum ApplicationStates {
96160
pub enum MessageKeys {
97161
#[strum(serialize = "status")]
98162
STATUS,
99-
#[strum(serialize = "connectedStatus")]
100-
CONNECTED_STATUS,
101-
#[strum(serialize = "bottomNavbarStatus")]
102-
BOTTOM_NAVBAR_STATUS,
163+
#[strum(serialize = "statusBarStatus")]
164+
STATUS_BAR_STATUS,
165+
#[strum(serialize = "navBarStatus")]
166+
NAV_BAR_STATUS,
103167
#[strum(serialize = "solutionPositionStatus")]
104168
SOLUTION_POSITION_STATUS,
105169
#[strum(serialize = "solutionTableStatus")]
@@ -134,6 +198,10 @@ pub enum MessageKeys {
134198
SOLUTION_POSITION_STATUS_BUTTON_FRONT,
135199
#[strum(serialize = "logAppend")]
136200
LOG_APPEND,
201+
#[strum(serialize = "loggingBarFront")]
202+
LOGGING_BAR_FRONT,
203+
#[strum(serialize = "loggingBarStatus")]
204+
LOGGING_BAR_STATUS,
137205
}
138206

139207
#[derive(Clone, Debug, Display, EnumString, EnumVariantNames, Eq, Hash, PartialEq)]

console_backend/src/constants.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub const VEL_TIME_STR_FILEPATH: &str = "velocity_log_%Y%m%d-%H%M%S.csv";
3434
pub const POS_LLH_TIME_STR_FILEPATH: &str = "position_log_%Y%m%d-%H%M%S.csv";
3535
pub const SBP_FILEPATH: &str = "swift-gnss-%Y%m%d-%H%M%S.sbp";
3636
pub const SBP_JSON_FILEPATH: &str = "swift-gnss-%Y%m%d-%H%M%S.sbp.json";
37+
pub const DEFAULT_LOG_DIRECTORY: &str = "SwiftNav";
3738

3839
// Common constants.
3940
pub const NUM_POINTS: usize = 200;

console_backend/src/main_tab.rs

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use log::{debug, error};
33
use sbp::{messages::SBP, time::GpsTime};
44
use std::{path::PathBuf, result::Result, thread::sleep, time::Instant};
55

6+
use crate::common_constants::SbpLogging;
67
use crate::constants::*;
78
use crate::observation_tab::ObservationTab;
89
use crate::output::*;
@@ -15,7 +16,7 @@ use crate::utils::refresh_loggingbar;
1516

1617
pub struct MainTab<'a, S: MessageSender> {
1718
logging_directory: PathBuf,
18-
last_solution_logging: CsvLogging,
19+
last_csv_logging: CsvLogging,
1920
last_sbp_logging: SbpLogging,
2021
sbp_logger: Option<SbpLogger>,
2122
last_gps_update: Instant,
@@ -32,9 +33,9 @@ pub struct MainTab<'a, S: MessageSender> {
3233
impl<'a, S: MessageSender> MainTab<'a, S> {
3334
pub fn new(shared_state: SharedState, client_sender: S) -> MainTab<'a, S> {
3435
MainTab {
35-
logging_directory: DATA_DIRECTORY.path(),
36-
last_solution_logging: CsvLogging::Off,
37-
last_sbp_logging: SbpLogging::Off,
36+
logging_directory: shared_state.logging_directory(),
37+
last_csv_logging: CsvLogging::OFF,
38+
last_sbp_logging: SbpLogging::OFF,
3839
sbp_logger: None,
3940
last_gps_time: None,
4041
last_gps_update: Instant::now(),
@@ -110,8 +111,10 @@ impl<'a, S: MessageSender> MainTab<'a, S> {
110111
None
111112
}
112113
};
114+
self.shared_state.set_csv_logging(CsvLogging::ON);
113115
}
114116
pub fn end_csv_logging(&mut self) -> crate::types::Result<()> {
117+
self.shared_state.set_csv_logging(CsvLogging::OFF);
115118
if let Some(vel_log) = &mut self.solution_tab.vel_log_file {
116119
vel_log.flush()?;
117120
self.solution_tab.vel_log_file = None;
@@ -130,7 +133,7 @@ impl<'a, S: MessageSender> MainTab<'a, S> {
130133
pub fn init_sbp_logging(&mut self, logging: SbpLogging) {
131134
let local_t = Local::now();
132135
self.sbp_logger = match logging {
133-
SbpLogging::Sbp => {
136+
SbpLogging::SBP => {
134137
let sbp_log_file = local_t.format(SBP_FILEPATH).to_string();
135138
let sbp_log_file = self.logging_directory.join(sbp_log_file);
136139
match SbpLogger::new_sbp(&sbp_log_file) {
@@ -141,7 +144,7 @@ impl<'a, S: MessageSender> MainTab<'a, S> {
141144
}
142145
}
143146
}
144-
SbpLogging::Json => {
147+
SbpLogging::SBP_JSON => {
145148
let sbp_json_log_file = local_t.format(SBP_JSON_FILEPATH).to_string();
146149
let sbp_json_log_file = self.logging_directory.join(sbp_json_log_file);
147150
match SbpLogger::new_sbp_json(&sbp_json_log_file) {
@@ -154,43 +157,49 @@ impl<'a, S: MessageSender> MainTab<'a, S> {
154157
}
155158
_ => None,
156159
};
160+
self.shared_state.set_sbp_logging(logging);
157161
}
158162
pub fn serialize_sbp(&mut self, msg: &SBP) {
159-
let solution_logging;
163+
let csv_logging;
160164
let sbp_logging;
161165
let directory;
162166
{
163167
let shared_data = self.shared_state.lock().unwrap();
164-
solution_logging = (*shared_data).logging_bar.solution_logging.clone();
168+
csv_logging = (*shared_data).logging_bar.csv_logging.clone();
165169
sbp_logging = (*shared_data).logging_bar.sbp_logging.clone();
166170
directory = (*shared_data).logging_bar.logging_directory.clone();
167171
}
168-
if self.last_solution_logging != solution_logging {
172+
self.logging_directory = self.shared_state.clone().logging_directory();
173+
174+
if self.logging_directory != directory {
175+
if let Err(e) = create_directory(directory.clone()) {
176+
error!("Issue creating directory {}.", e);
177+
self.shared_state
178+
.set_logging_directory(self.logging_directory.clone());
179+
} else {
180+
self.shared_state.update_folder_history(directory.clone());
181+
self.logging_directory = directory;
182+
}
183+
refresh_loggingbar(&mut self.client_sender, self.shared_state.clone());
184+
}
185+
186+
if self.last_csv_logging != csv_logging {
169187
if let Err(e) = self.end_csv_logging() {
170188
error!("Issue closing csv file, {}", e);
171189
}
172-
if let CsvLogging::On = &solution_logging {
190+
if let CsvLogging::ON = &csv_logging {
173191
self.init_csv_logging();
174192
}
175-
self.last_solution_logging = solution_logging;
193+
self.last_csv_logging = csv_logging;
194+
refresh_loggingbar(&mut self.client_sender, self.shared_state.clone());
176195
}
177196
if self.last_sbp_logging != sbp_logging {
178197
self.close_sbp();
179-
if let SbpLogging::Off = &sbp_logging {
198+
if let SbpLogging::OFF = &sbp_logging {
180199
} else {
181200
self.init_sbp_logging(sbp_logging.clone());
182201
}
183202
self.last_sbp_logging = sbp_logging;
184-
}
185-
if self.logging_directory != directory {
186-
if let Err(e) = create_directory(directory.clone()) {
187-
error!("Issue creating directory {}.", e);
188-
self.shared_state
189-
.set_logging_directory(self.logging_directory.clone());
190-
} else {
191-
self.shared_state.update_folder_history(directory.clone());
192-
self.logging_directory = directory;
193-
}
194203
refresh_loggingbar(&mut self.client_sender, self.shared_state.clone());
195204
}
196205

@@ -201,6 +210,7 @@ impl<'a, S: MessageSender> MainTab<'a, S> {
201210
}
202211
}
203212
pub fn close_sbp(&mut self) {
213+
self.shared_state.set_sbp_logging(SbpLogging::OFF);
204214
self.sbp_logger = None;
205215
}
206216
}

console_backend/src/output.rs

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,44 +10,26 @@ use serde::Serialize;
1010
use serde_json::ser::CompactFormatter;
1111
use std::{fs::File, path::Path};
1212

13+
use crate::common_constants as cc;
1314
use crate::types::Result;
1415

15-
#[derive(Clone, Debug, PartialEq)]
16-
pub enum CsvLogging {
17-
Off,
18-
On,
19-
}
16+
pub type CsvLogging = cc::CsvLogging;
2017
impl From<bool> for CsvLogging {
2118
fn from(logging: bool) -> Self {
2219
if logging {
23-
CsvLogging::On
20+
CsvLogging::ON
2421
} else {
25-
CsvLogging::Off
22+
CsvLogging::OFF
2623
}
2724
}
2825
}
29-
30-
#[derive(Clone, Debug, PartialEq)]
31-
pub enum SbpLogging {
32-
Off,
33-
Sbp,
34-
Json,
35-
}
36-
impl From<(bool, bool)> for SbpLogging {
37-
fn from(logging_and_format: (bool, bool)) -> Self {
38-
let (sbp_logging, sbp_format) = logging_and_format;
39-
if sbp_logging {
40-
if sbp_format {
41-
SbpLogging::Sbp
42-
} else {
43-
SbpLogging::Json
44-
}
45-
} else {
46-
SbpLogging::Off
47-
}
26+
impl CsvLogging {
27+
pub fn to_bool(&self) -> bool {
28+
matches!(self, CsvLogging::ON)
4829
}
4930
}
5031

32+
pub type SbpLogging = cc::SbpLogging;
5133
pub enum SbpLogger {
5234
Sbp(FramedWrite<File, SbpEncoder>),
5335
Json(FramedWrite<File, JsonEncoder<CompactFormatter>>),

0 commit comments

Comments
 (0)