Skip to content

Commit 1aebe7b

Browse files
authored
Add ntrip client [main branch] [CPP-952] (#1088)
Ports NTRIP client support to the main branch: #1033
1 parent 5fc0bb4 commit 1aebe7b

31 files changed

+1081
-27
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
"console_backend/tests/data/*" filter=lfs diff=lfs merge=lfs -text
22
installers/Windows/NSIS/*.zip filter=lfs diff=lfs merge=lfs -text
3+
binaries/** filter=lfs diff=lfs merge=lfs -text

Makefile.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,12 @@ args = [
311311
command = "${DIST_PYTHON}"
312312
args = ["-m", "pip", "install", "flit"]
313313

314+
[tasks.check-git-status]
315+
command = "git"
316+
args = ["status"]
317+
314318
[tasks.build-frontend-wheel]
315-
dependencies = ["dist-install-pip-flit"]
319+
dependencies = ["dist-install-pip-flit", "check-git-status"]
316320
command = "${DIST_PYTHON}"
317321
args = ["-m", "flit", "build", "--no-setup-py"]
318322

@@ -572,6 +576,9 @@ args = ["-m", "pip", "install", "console_backend/dist/${BACKEND_WHEEL}"]
572576
script_runner = "@duckscript"
573577
script = '''
574578
cp src/main/resources py311-dist/
579+
580+
os = os_family
581+
glob_cp binaries/${os}/rtcm3tosbp* py311-dist/binaries/${os}
575582
'''
576583

577584
[tasks.build-dist-freeze]

binaries/linux/rtcm3tosbp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:7e6c5a8c70d9a15689037b4b6f98fce0f647caa3b6d4448731951bffe27ce291
3+
size 809440

binaries/mac/rtcm3tosbp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:f31913dd402a2c98f0ea792a1ae4a58608ee98557a38525b80da3fc59b26624a
3+
size 795824

binaries/windows/rtcm3tosbp.exe

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:c01f35d1c955c418590e2c87d328f54c0c067a0d8af8773968211e7a50031981
3+
size 814080

console_backend/src/cli_options.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ pub struct CliOptions {
105105
#[clap(long)]
106106
pub enable_map: bool,
107107

108+
/// Enable ntrip client
109+
#[clap(long)]
110+
pub enable_ntrip: bool,
111+
108112
/// Path to a yaml file containing known piksi settings.
109113
#[clap(long)]
110114
pub settings_yaml: Option<PathBuf>,

console_backend/src/common_constants.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,8 @@ pub enum Keys {
293293
NOTIFICATION,
294294
#[strum(serialize = "SOLUTION_LINE")]
295295
SOLUTION_LINE,
296+
#[strum(serialize = "NTRIP_DISPLAY")]
297+
NTRIP_DISPLAY,
296298
}
297299

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

console_backend/src/connection.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ fn conn_manager_thd(
182182
ConnectionState::Connected {
183183
conn: conn.clone(),
184184
stop_token,
185+
msg_sender: msg_sender.clone(),
185186
},
186187
&client_sender,
187188
);

console_backend/src/lib.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub mod fft_monitor;
3232
pub mod fileio;
3333
pub mod fusion_status_flags;
3434
pub mod log_panel;
35+
pub mod ntrip_output;
3536
pub mod output;
3637
pub mod piksi_tools_constants;
3738
pub mod process_messages;
@@ -47,9 +48,9 @@ pub mod updater;
4748
pub mod utils;
4849
pub mod watch;
4950

51+
use crate::client_sender::BoxedClientSender;
52+
use crate::shared_state::SharedState;
5053
use crate::status_bar::StatusBar;
51-
use std::sync::Mutex;
52-
5354
use crate::tabs::{
5455
advanced_tab::{
5556
advanced_imu_tab::AdvancedImuTab, advanced_magnetometer_tab::AdvancedMagnetometerTab,
@@ -69,6 +70,8 @@ use crate::tabs::{
6970
},
7071
update_tab::UpdateTab,
7172
};
73+
use crate::types::MsgSender;
74+
use std::sync::Mutex;
7275

7376
#[global_allocator]
7477
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
@@ -89,13 +92,14 @@ struct Tabs {
8992
pub status_bar: Mutex<StatusBar>,
9093
pub update: Mutex<UpdateTab>,
9194
pub settings: Option<SettingsTab>, // settings only enabled on TCP / Serial
95+
pub shared_state: SharedState,
9296
}
9397

9498
impl Tabs {
9599
fn new(
96-
shared_state: shared_state::SharedState,
97-
client_sender: client_sender::BoxedClientSender,
98-
msg_sender: types::MsgSender,
100+
shared_state: SharedState,
101+
client_sender: BoxedClientSender,
102+
msg_sender: MsgSender,
99103
) -> Self {
100104
Self {
101105
main: MainTab::new(shared_state.clone(), client_sender.clone()).into(),
@@ -139,15 +143,16 @@ impl Tabs {
139143
)
140144
.into(),
141145
status_bar: StatusBar::new(shared_state.clone()).into(),
142-
update: UpdateTab::new(shared_state).into(),
146+
update: UpdateTab::new(shared_state.clone()).into(),
143147
settings: None,
148+
shared_state,
144149
}
145150
}
146151

147152
fn with_settings(
148-
shared_state: shared_state::SharedState,
149-
client_sender: client_sender::BoxedClientSender,
150-
msg_sender: types::MsgSender,
153+
shared_state: SharedState,
154+
client_sender: BoxedClientSender,
155+
msg_sender: MsgSender,
151156
) -> Self {
152157
let mut tabs = Self::new(
153158
shared_state.clone(),
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
use crate::tabs::advanced_tab::ntrip_tab::OutputType;
2+
use crate::types::Result;
3+
use crate::utils::pythonhome_dir;
4+
use anyhow::Context;
5+
use crossbeam::channel::Receiver;
6+
use log::{error, info};
7+
use std::io::Write;
8+
use std::process::{Command, Stdio};
9+
use std::{io, thread};
10+
11+
pub struct MessageConverter {
12+
in_rx: Receiver<Vec<u8>>,
13+
output_type: OutputType,
14+
}
15+
16+
impl MessageConverter {
17+
pub fn new(in_rx: Receiver<Vec<u8>>, output_type: OutputType) -> Self {
18+
Self { in_rx, output_type }
19+
}
20+
21+
pub fn start<W: Write + Send + 'static>(&mut self, out: W) -> Result<()> {
22+
match self.output_type {
23+
OutputType::RTCM => self.output_rtcm(out),
24+
OutputType::SBP => self.output_sbp(out),
25+
}
26+
}
27+
28+
/// Just redirects directly to writer
29+
fn output_rtcm<W: Write + Send + 'static>(&mut self, mut out: W) -> Result<()> {
30+
let in_rx = self.in_rx.clone();
31+
thread::spawn(move || loop {
32+
if let Ok(data) = in_rx.recv() {
33+
if let Err(e) = out.write(&data) {
34+
error!("failed to write to device {e}");
35+
}
36+
}
37+
});
38+
Ok(())
39+
}
40+
41+
/// Runs rtcm3tosbp converter
42+
fn output_sbp<W: Write + Send + 'static>(&mut self, mut out: W) -> Result<()> {
43+
let mut child = if cfg!(target_os = "windows") {
44+
let mut cmd = Command::new("cmd");
45+
let rtcm = pythonhome_dir()?
46+
.join("binaries")
47+
.join("windows")
48+
.join("rtcm3tosbp.exe")
49+
.to_string_lossy()
50+
.to_string();
51+
info!("running rtcm3tosbp from \"{}\"", rtcm);
52+
cmd.args(["/C", &rtcm]);
53+
cmd
54+
} else if cfg!(target_os = "macos") {
55+
let mut cmd = Command::new("sh");
56+
let rtcm = pythonhome_dir()?
57+
.join("binaries")
58+
.join("mac")
59+
.join("rtcm3tosbp")
60+
.to_string_lossy()
61+
.to_string();
62+
info!("running rtcm3tosbp from \"{}\"", rtcm);
63+
cmd.args(["-c", &rtcm]);
64+
cmd
65+
} else {
66+
let mut cmd = Command::new("sh");
67+
let rtcm = pythonhome_dir()?
68+
.join("binaries")
69+
.join("linux")
70+
.join("rtcm3tosbp")
71+
.to_string_lossy()
72+
.to_string();
73+
info!("running rtcm3tosbp from \"{}\"", rtcm);
74+
cmd.args(["-c", &rtcm]);
75+
cmd
76+
};
77+
let mut child = child
78+
.stdin(Stdio::piped())
79+
.stdout(Stdio::piped())
80+
.stderr(Stdio::null())
81+
.spawn()
82+
.context("rtcm converter process failed")?;
83+
84+
let mut child_in = child.stdin.take().context("rtcm3tosbp stdin missing")?;
85+
let mut child_out = child.stdout.take().context("rtcm3tosbp stdout missing")?;
86+
let in_rx = self.in_rx.clone();
87+
88+
thread::spawn(move || {
89+
if let Err(e) = io::copy(&mut child_out, &mut out) {
90+
error!("failed to write to device {e}");
91+
}
92+
});
93+
thread::spawn(move || {
94+
while let Ok(data) = in_rx.recv() {
95+
if let Err(e) = child_in.write_all(&data) {
96+
error!("failed to write to rtcm3tosbp {e}")
97+
}
98+
}
99+
});
100+
thread::spawn(move || child.wait());
101+
Ok(())
102+
}
103+
}

0 commit comments

Comments
 (0)