diff --git a/README.md b/README.md index dd48d4a..09c3c94 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Boston Center ``` { "airport": "KBOS", - The airport to view aircraft at + "delay": 15, - How much time to buffer before displaying aircraft, useful for syncing with LiveATC "range": 30, - How far away from the airport (in miles) aircraft should be shown "floor": 0, - Aircraft below this altitude (in feet) will not be displayed "ceiling": 99999, - Aircraft above this altitude will not be displayed diff --git a/config.json b/config.json index 807b5ec..3f6bf95 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,7 @@ { "airport": "KBOS", "range": 30, + "delay": 15, "floor": 0, "ceiling": 99999 } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index a602d75..8f551e2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -62,6 +62,7 @@ struct TrackedData { struct ConfigData { airport: String, range: u32, + delay: u64, floor: i32, ceiling: i32, } @@ -107,10 +108,13 @@ fn main() { // Map to keep track of data already injected let mut injected_tracker: HashMap = HashMap::new(); - let mut timer = Instant::now(); let mut current_callsign = String::new(); + let mut timer = Instant::now(); + let buffer_timer = Instant::now(); println!("Displaying aircraft..."); + + tracker.start_buffering(); 'main: loop { tracker.step(); @@ -137,13 +141,26 @@ fn main() { std::thread::sleep(std::time::Duration::from_millis(1)); } - // Reset timer - if should_update_position { + if should_update_position { // AKA 3 second intervals + // Reset position update timer timer = Instant::now(); - println!("Updating aircraft: {} shown.\r", aircraft_count); + + // Manage buffering + if tracker.is_buffering() { + let elaspsed = buffer_timer.elapsed().as_secs(); + if elaspsed >= config.delay { + tracker.stop_buffering(); + } + else { + println!("Buffering... {} seconds left to buffer.", (config.delay-elaspsed).max(0)); + } + } + else { + println!("Updating aircraft: {} shown.", aircraft_count); + } } - // Remove untracked + // Remove dropped off radar aircraft for id in injected_tracker.keys().map(|x| x.clone()).collect::>() { if tracker.aircraft_exists(&id) {continue} injected_tracker.remove(&id); diff --git a/src/tracker.rs b/src/tracker.rs index fdeb7a2..1db64b6 100644 --- a/src/tracker.rs +++ b/src/tracker.rs @@ -1,13 +1,17 @@ -use std::{collections::HashMap, time::Instant, collections::HashSet, collections::hash_map::Keys}; +use std::{collections::HashMap, time::Instant, collections::{HashSet, VecDeque}, collections::hash_map::Keys}; use crate::util::Bounds; use crate::{flightradar::{AircraftData, FlightRadar}, interpolate::InterpolatePosition}; use crate::flightaware::{FlightPlan, FlightAware}; +const POLL_RATE: u64 = 3; + pub struct Tracker { radar: FlightRadar, faware: FlightAware, + buffer: VecDeque>, + is_buffering: bool, tracking: HashMap, callsign_set: HashSet, time: Instant, @@ -21,6 +25,9 @@ impl Tracker { Self { radar: FlightRadar::new(radar_loc), faware: FlightAware::new(), + + buffer: VecDeque::new(), + is_buffering: false, tracking: HashMap::new(), callsign_set: HashSet::new(), time: Instant::now(), @@ -87,12 +94,25 @@ impl Tracker { } } + fn get_next_aircraft_update(&mut self) -> Option> { + if let Ok(aircraft) = self.radar.get_aircraft() { + self.buffer.push_back(aircraft); + } + + if !self.is_buffering { + return self.buffer.pop_front(); + } else { + return None; + } + } + fn update_aircraft(&mut self) { - let aircraft = self.radar.get_aircraft(); - if aircraft.is_err() {return;} - let aircraft = aircraft.as_ref().unwrap(); + let aircraft = match self.get_next_aircraft_update() { + Some(a) => a, + None => return + }; - for (id, aircraft) in aircraft { + for (id, aircraft) in aircraft.iter() { // Invalid callsigns/callsign not received if aircraft.callsign.trim() == "" {continue} if aircraft.altitude < self.floor || aircraft.altitude > self.ceiling {continue} @@ -126,13 +146,25 @@ impl Tracker { pub fn step(&mut self) { let elasped = self.time.elapsed().as_secs(); - if elasped > 3 { + if elasped > POLL_RATE { self.update_aircraft(); self.time = Instant::now(); } self.step_flightplan(); } + + pub fn start_buffering(&mut self) { + self.is_buffering = true; + } + + pub fn stop_buffering(&mut self) { + self.is_buffering = false; + } + + pub fn is_buffering(&self) -> bool { + self.is_buffering + } } #[derive(Default)]