use crate::{
args::Args,
fpga::{InterruptHandler, IpCore},
httpd::{self, RecorderFinishWaiter, RecorderState},
iio::Ad9361,
spectrometer::{Spectrometer, SpectrometerConfig},
};
use anyhow::Result;
use std::sync::{Arc, Mutex};
use tokio::sync::broadcast;
#[derive(Debug)]
pub struct App {
httpd: httpd::Server,
interrupt_handler: InterruptHandler,
recorder_finish: RecorderFinishWaiter,
spectrometer: Spectrometer,
}
impl App {
#[tracing::instrument(name = "App::new", level = "debug")]
pub async fn new(args: &Args) -> Result<App> {
let (ip_core, interrupt_handler) = IpCore::take().await?;
let ip_core = std::sync::Mutex::new(ip_core);
let ad9361 = tokio::sync::Mutex::new(Ad9361::new().await?);
let recorder = RecorderState::new(&ad9361, &ip_core).await?;
let state = AppState(Arc::new(State {
ad9361,
ip_core,
geolocation: std::sync::Mutex::new(None),
recorder,
spectrometer_config: Default::default(),
}));
state.spectrometer_config().set_samp_rate_mode(
state.ad9361().lock().await.get_sampling_frequency().await? as f32,
state.ip_core().lock().unwrap().spectrometer_mode(),
);
let (waterfall_sender, _) = broadcast::channel(16);
let spectrometer = Spectrometer::new(
state.clone(),
interrupt_handler.waiter_spectrometer(),
waterfall_sender.clone(),
);
let recorder_finish =
RecorderFinishWaiter::new(state.clone(), interrupt_handler.waiter_recorder());
let httpd = httpd::Server::new(
args.listen,
args.listen_https,
args.ssl_cert.as_ref(),
args.ssl_key.as_ref(),
args.ca_cert.as_ref(),
state,
waterfall_sender,
)
.await?;
Ok(App {
httpd,
interrupt_handler,
recorder_finish,
spectrometer,
})
}
#[tracing::instrument(name = "App::run", level = "debug", skip_all)]
pub async fn run(self) -> Result<()> {
tokio::select! {
ret = self.httpd.run() => ret,
ret = self.interrupt_handler.run() => ret,
ret = self.recorder_finish.run() => ret,
ret = self.spectrometer.run() => ret,
}
}
}
#[derive(Debug, Clone)]
pub struct AppState(Arc<State>);
#[derive(Debug)]
struct State {
ad9361: tokio::sync::Mutex<Ad9361>,
ip_core: Mutex<IpCore>,
geolocation: Mutex<Option<maia_json::Geolocation>>,
recorder: RecorderState,
spectrometer_config: SpectrometerConfig,
}
impl AppState {
pub fn ad9361(&self) -> &tokio::sync::Mutex<Ad9361> {
&self.0.ad9361
}
pub fn ip_core(&self) -> &Mutex<IpCore> {
&self.0.ip_core
}
pub fn geolocation(&self) -> &Mutex<Option<maia_json::Geolocation>> {
&self.0.geolocation
}
pub fn recorder(&self) -> &RecorderState {
&self.0.recorder
}
pub fn spectrometer_config(&self) -> &SpectrometerConfig {
&self.0.spectrometer_config
}
pub async fn ad9361_samp_rate(&self) -> Result<f64> {
Ok(self.ad9361().lock().await.get_sampling_frequency().await? as f64)
}
}