Skip to content

Commit eb0acbc

Browse files
committed
feat: add --interactive-expire option for configurable aircraft display timeout
1 parent c739daf commit eb0acbc

File tree

3 files changed

+38
-6
lines changed

3 files changed

+38
-6
lines changed

crates/jet1090/src/main.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,18 @@ struct Options {
7474
#[arg(long, conflicts_with = "history_expire")]
7575
no_history_expire: Option<bool>,
7676

77+
/// How long to keep aircraft visible in interactive mode (in seconds), 0 for no expiration
78+
#[arg(
79+
long,
80+
default_value = "30",
81+
conflicts_with = "no_interactive_expire"
82+
)]
83+
interactive_expire: Option<u64>,
84+
85+
/// Disable interactive mode aircraft expiration
86+
#[arg(long, conflicts_with = "interactive_expire")]
87+
no_interactive_expire: Option<bool>,
88+
7789
/// Downlink formats to select for stdout, file output and history in REST API (keep empty to select all)
7890
#[arg(long, value_name = "DF")]
7991
df_filter: Option<Vec<u16>>,
@@ -194,6 +206,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
194206
options.history_expire = Some(history_expire);
195207
}
196208
}
209+
if cli_options.no_interactive_expire.is_some_and(|x| x) {
210+
options.interactive_expire = Some(0);
211+
} else if let Some(interactive_expire) = cli_options.interactive_expire {
212+
if interactive_expire == 30
213+
&& cli_options.no_interactive_expire.is_some_and(|x| x)
214+
{
215+
options.interactive_expire = Some(0);
216+
} else {
217+
options.interactive_expire = Some(interactive_expire);
218+
}
219+
}
197220
if cli_options.df_filter.is_some() {
198221
options.df_filter = cli_options.df_filter;
199222
}
@@ -341,6 +364,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
341364
width,
342365
is_search_mode: false,
343366
search_query: "".to_string(),
367+
interactive_expire: options.interactive_expire.unwrap_or(30),
344368
}));
345369
let app_dec = app_tui.clone();
346370
let app_web = app_tui.clone();
@@ -583,6 +607,7 @@ pub struct Jet1090 {
583607
width: u16,
584608
is_search_mode: bool,
585609
search_query: String,
610+
interactive_expire: u64,
586611
}
587612

588613
#[derive(Debug, Default, PartialEq)]

crates/jet1090/src/source.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ use rs1090::source::sero;
1111
#[cfg(feature = "ssh")]
1212
use rs1090::source::ssh::{TunnelledTcp, TunnelledWebsocket};
1313

14-
#[cfg(feature = "sdr")]
15-
use desperado::IqAsyncSource;
1614
#[cfg(feature = "pluto")]
1715
use desperado::pluto::PlutoConfig;
1816
#[cfg(feature = "rtlsdr")]
1917
use desperado::rtlsdr::{DeviceSelector, RtlSdrConfig};
2018
#[cfg(feature = "soapy")]
2119
use desperado::soapy::SoapyConfig;
2220
#[cfg(feature = "sdr")]
21+
use desperado::IqAsyncSource;
22+
#[cfg(feature = "sdr")]
2323
use desperado::{DeviceConfig, Gain};
2424
use serde::{Deserialize, Serialize};
2525
use tokio::sync::mpsc::Sender;

crates/jet1090/src/table.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ pub fn build_table(frame: &mut Frame, app: &mut Jet1090) {
2525

2626
let states = &app.state_vectors;
2727

28+
// Get the interactive expire threshold (0 means no expiration)
29+
let interactive_expire = app.interactive_expire;
30+
2831
// Filter items based on search query
2932
let search_query = app.search_query.to_lowercase().replace("-", "");
3033
let search_regex =
@@ -33,8 +36,8 @@ pub fn build_table(frame: &mut Frame, app: &mut Jet1090) {
3336
.values()
3437
.filter(|sv| {
3538
(sv.cur.count > 1)
36-
// Only show aircraft seen in the last 30 seconds
37-
&& (now as i64 - sv.cur.lastseen as i64) < 30
39+
// Only show aircraft seen within the expiration threshold (or always if 0)
40+
&& (interactive_expire == 0 || (now as i64 - sv.cur.lastseen as i64) < interactive_expire as i64)
3841
&& (sv.cur.callsign.as_ref().is_some_and(|s| {
3942
search_regex.is_match(&s.to_lowercase())
4043
}) || search_regex
@@ -203,8 +206,12 @@ pub fn build_table(frame: &mut Frame, app: &mut Jet1090) {
203206
};
204207
let rows = sorted_elts
205208
.iter()
206-
// Only show aircraft seen in the last 30 seconds
207-
.filter(|sv| (now as i64 - sv.cur.lastseen as i64) < 30)
209+
// Only show aircraft seen within the expiration threshold (or always if 0)
210+
.filter(|sv| {
211+
interactive_expire == 0
212+
|| (now as i64 - sv.cur.lastseen as i64)
213+
< interactive_expire as i64
214+
})
208215
.enumerate()
209216
.map(|(i, sv)| {
210217
let color = match i % 2 {

0 commit comments

Comments
 (0)