Skip to content

Commit e1786a3

Browse files
john-michaelburkeJason Mobarak
andauthored
Headless runner for console[CPP-318]. (#123)
* Headless runner for console. * Update console_backend/Cargo.toml Co-authored-by: Jason Mobarak <[email protected]> * Log messages. Co-authored-by: Jason Mobarak <[email protected]>
1 parent c1eeb4e commit e1786a3

30 files changed

+1344
-1166
lines changed

Cargo.lock

Lines changed: 9 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Makefile.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,18 @@ dependencies = [
152152
]
153153
run_task = "start-console"
154154

155+
[tasks.headless-run]
156+
command = "cargo"
157+
args = [
158+
"run",
159+
"--bin",
160+
"headless-console",
161+
"--features",
162+
"headless-console",
163+
"--no-default-features",
164+
"${@}",
165+
]
166+
155167
[tasks.store-version]
156168
script_runner = "@shell"
157169
script = '''

console_backend/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ minreq = { version = "2.4.2", features = ["https"] }
4040
regex = { version = "1.5.4" }
4141
semver = { version = "1" }
4242
rust-ini = "0.17.0"
43+
snap = { version = "1", optional = true }
4344

4445
[dependencies.sbp]
4546
git = "https://github.com/swift-nav/libsbp.git"
@@ -80,8 +81,15 @@ path = "src/bin/fft_monitor.rs"
8081
bench = false
8182
required-features = ["fft"]
8283

84+
[[bin]]
85+
name = "headless-console"
86+
path = "src/bin/headless-console.rs"
87+
bench = false
88+
required-features = ["headless-console"]
89+
8390
[features]
8491
default = ["pyo3"]
8592
benches = []
8693
tests = []
8794
fft = ["serde-pickle"]
95+
headless-console = ["snap"]

console_backend/benches/cpu_benches.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ extern crate console_backend;
1414
use console_backend::{
1515
connection::Connection,
1616
process_messages,
17-
types::{ClientSender, RealtimeDelay, SharedState},
17+
shared_state::SharedState,
18+
types::{ClientSender, RealtimeDelay},
1819
};
1920

2021
const BENCH_FILEPATH: &str = "./tests/data/piksi-relay.sbp";

console_backend/src/advanced_ins_tab.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ use capnp::message::Builder;
66
use crate::constants::*;
77
use crate::errors::GET_MUT_OBJECT_FAILURE;
88
use crate::fusion_status_flags::FusionStatusFlags;
9-
use crate::types::{CapnProtoSender, Deque, SharedState};
9+
use crate::shared_state::SharedState;
10+
use crate::types::{CapnProtoSender, Deque};
1011
use crate::utils::serialize_capnproto_builder;
1112

1213
/// AdvancedInsTab struct.

console_backend/src/advanced_magnetometer_tab.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use capnp::message::Builder;
44

55
use crate::constants::{MAGNETOMETER_Y_AXIS_PADDING_MULTIPLIER, NUM_POINTS};
66
use crate::errors::GET_MUT_OBJECT_FAILURE;
7-
use crate::types::{CapnProtoSender, Deque, SharedState};
7+
use crate::shared_state::SharedState;
8+
use crate::types::{CapnProtoSender, Deque};
89
use crate::utils::serialize_capnproto_builder;
910

1011
/// AdvancedMagnetometerTab struct.

console_backend/src/advanced_spectrum_analyzer_tab.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use log::error;
33
use crate::constants::{AMPLITUDES, CHANNELS, FREQUENCIES};
44
use crate::errors::SHARED_STATE_LOCK_MUTEX_FAILURE;
55
use crate::fft_monitor::FftMonitor;
6-
use crate::types::{CapnProtoSender, SharedState, Specan};
6+
use crate::shared_state::SharedState;
7+
use crate::types::{CapnProtoSender, Specan};
78
use crate::utils::serialize_capnproto_builder;
89
use capnp::message::Builder;
910

console_backend/src/baseline_tab.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ use crate::constants::*;
1212
use crate::date_conv::*;
1313
use crate::output::BaselineLog;
1414
use crate::piksi_tools_constants::EMPTY_STR;
15+
use crate::shared_state::SharedState;
1516
use crate::types::{
16-
BaselineNED, CapnProtoSender, Deque, GnssModes, GpsTime, MsgSender, Result, SharedState,
17-
UtcDateTime,
17+
BaselineNED, CapnProtoSender, Deque, GnssModes, GpsTime, MsgSender, Result, UtcDateTime,
1818
};
1919
use crate::utils::*;
2020

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use anyhow::Result;
2+
use chrono::prelude::*;
3+
use console_backend::{
4+
cli_options::{handle_cli, CliOptions},
5+
connection::ConnectionState,
6+
log_panel::setup_logging,
7+
server_recv_thread::server_recv_thread,
8+
shared_state::SharedState,
9+
types::ClientSender,
10+
utils::{refresh_loggingbar, refresh_navbar},
11+
};
12+
use crossbeam::channel;
13+
use std::fs::File;
14+
use std::io::{prelude::*, BufWriter};
15+
16+
fn main() -> Result<()> {
17+
let opt = CliOptions::from_filtered_cli();
18+
if opt.input.is_none() {
19+
eprintln!(
20+
r#"
21+
Running in headless mode only command line options work.
22+
Help:
23+
./headless-console --help
24+
Usage:
25+
./headless-console tcp piksi-relay-bb9f2b10e53143f4a816a11884e679cf.ce.swiftnav.com --port=55555
26+
"#
27+
);
28+
return Ok(());
29+
}
30+
let (client_send_, client_recv) = channel::unbounded::<Vec<u8>>();
31+
let (_server_send, server_recv) = channel::unbounded::<Vec<u8>>();
32+
let client_send = ClientSender::new(client_send_);
33+
setup_logging(client_send.clone(), true);
34+
let shared_state = SharedState::new();
35+
let connection_state = ConnectionState::new(client_send.clone(), shared_state.clone());
36+
handle_cli(opt, &connection_state, shared_state.clone());
37+
refresh_navbar(&mut client_send.clone(), shared_state.clone());
38+
refresh_loggingbar(&mut client_send.clone(), shared_state.clone());
39+
server_recv_thread(connection_state, client_send, server_recv, shared_state);
40+
41+
let local: DateTime<Local> = Local::now();
42+
let mut filename = format!("headless-console-{}.data", local);
43+
filename.retain(|c| !c.is_whitespace());
44+
let file_out = File::create(filename)?;
45+
let buf_out = BufWriter::new(file_out);
46+
let mut msg_count: usize = 0;
47+
let mut file_out = snap::write::FrameEncoder::new(buf_out);
48+
while let Ok(msg) = client_recv.recv() {
49+
match file_out.write_all(&msg) {
50+
Ok(_) => {
51+
msg_count += 1;
52+
if msg_count % 100 == 0 {
53+
println!("Messages received: {}", msg_count);
54+
}
55+
}
56+
Err(err) => {
57+
eprintln!("{}", err);
58+
}
59+
}
60+
}
61+
Ok(())
62+
}

console_backend/src/cli_options.rs

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@ use std::{
77
use strum::VariantNames;
88

99
use crate::constants::{AVAILABLE_BAUDRATES, AVAILABLE_REFRESH_RATES};
10+
use crate::errors::{CONVERT_TO_STR_FAILURE, SHARED_STATE_LOCK_MUTEX_FAILURE};
1011
use crate::log_panel::LogLevel;
11-
use crate::types::FlowControl;
12+
use crate::output::CsvLogging;
13+
use crate::shared_state::SharedState;
14+
use crate::types::{FlowControl, RealtimeDelay};
1215
use crate::{
1316
common_constants::{SbpLogging, Tabs},
14-
connection::Connection,
17+
connection::{Connection, ConnectionState},
1518
};
1619

1720
#[derive(Debug)]
@@ -233,3 +236,48 @@ fn is_baudrate(br: &str) -> Result<(), String> {
233236
AVAILABLE_BAUDRATES
234237
))
235238
}
239+
240+
/// Start connections based on CLI options.
241+
///
242+
/// # Parameters
243+
/// - `opt`: CLI Options to start specific connection type.
244+
/// - `connection_state`: The Server state to start a specific connection.
245+
/// - `client_send`: Client Sender channel for communication from backend to frontend.
246+
/// - `shared_state`: The shared state for validating another connection is not already running.
247+
pub fn handle_cli(opt: CliOptions, connection_state: &ConnectionState, shared_state: SharedState) {
248+
if let Some(opt_input) = opt.input {
249+
match opt_input {
250+
Input::Tcp { host, port } => {
251+
connection_state.connect_to_host(host, port);
252+
}
253+
Input::File { file_in } => {
254+
let filename = file_in.display().to_string();
255+
connection_state.connect_to_file(filename, RealtimeDelay::On, opt.exit_after);
256+
}
257+
Input::Serial {
258+
serialport,
259+
baudrate,
260+
flow_control,
261+
} => {
262+
let serialport = serialport.display().to_string();
263+
connection_state.connect_to_serial(serialport, baudrate, flow_control);
264+
}
265+
}
266+
}
267+
if let Some(folder) = opt.dirname {
268+
shared_state.set_logging_directory(PathBuf::from(folder));
269+
}
270+
let log_level = if let Some(log_level_) = opt.log_level {
271+
(*log_level_).clone()
272+
} else {
273+
LogLevel::INFO
274+
};
275+
shared_state.set_log_level(log_level);
276+
let mut shared_data = shared_state.lock().expect(SHARED_STATE_LOCK_MUTEX_FAILURE);
277+
(*shared_data).logging_bar.csv_logging = CsvLogging::from(opt.csv_log);
278+
if let Some(sbp_log) = opt.sbp_log {
279+
(*shared_data).logging_bar.sbp_logging =
280+
SbpLogging::from_str(&sbp_log.to_string()).expect(CONVERT_TO_STR_FAILURE);
281+
}
282+
log::logger().flush();
283+
}

0 commit comments

Comments
 (0)