Skip to content

Commit

Permalink
Merge pull request #9 from mat-kie/redesign
Browse files Browse the repository at this point in the history
Redesign to reduce boilerplate code. Reorganize files
  • Loading branch information
mat-kie authored Dec 8, 2024
2 parents 966a321 + 00a261e commit bc29a9a
Show file tree
Hide file tree
Showing 20 changed files with 1,993 additions and 2,125 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ Cargo.lock

# misc
.hide*
.vscode
.vscode
NOTES.md
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ mockall = "0.13.1"
rand = "0.8.5"
typetag = "0.2.18"
anyhow = { version = "1.0.94", features = ["backtrace"] }
rust-fsm = "0.7.0"
event_bridge = "0.3.1"
210 changes: 210 additions & 0 deletions src/api/controller.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
//! Controller Module
//!
//! This module defines the traits and structures for managing the application's core functionalities,
//! including recording, storage, and Bluetooth interactions. It provides a set of asynchronous APIs
//! to handle various operations such as starting/stopping recordings, loading/storing data, and managing
//! Bluetooth devices.
use crate::model::bluetooth::{AdapterDescriptor, DeviceDescriptor, HeartrateMessage};
use anyhow::Result;
use async_trait::async_trait;
use btleplug::api::Central;
use std::{path::PathBuf, sync::Arc};
use time::Duration;
use tokio::sync::RwLock;

use super::model::{BluetoothModelApi, MeasurementModelApi};

#[derive(Clone, Debug)]
pub enum OutlierFilter {
MovingMAD { parameter: f64, _window: usize },
}

/// RecordingApi trait
///
/// This trait defines the asynchronous API for managing the recording process in the application.
/// It provides methods to start and stop the recording process.
#[async_trait]
pub trait RecordingApi {
/// start the recording process
async fn start_recording(&mut self) -> Result<()>;
/// stop the recording process
async fn stop_recording(&mut self) -> Result<()>;
}

/// StorageEventApi trait
///
/// This trait defines the asynchronous API for managing storage-related events in the application.
/// It provides methods to clear storage, load data from a file, store data to a file, and handle
/// new and recorded measurements.
#[async_trait]
pub trait StorageEventApi {
/// Clear the storage.
///
/// This method clears all the stored data.
async fn clear(&mut self) -> Result<()>;

/// Load data from a file.
///
/// This method loads data from the specified file path.
///
/// # Arguments
///
/// * `path` - A `PathBuf` representing the file path from which to load data.
async fn load_from_file(&mut self, path: PathBuf) -> Result<()>;

/// Store data to a file.
///
/// This method stores data to the specified file path.
///
/// # Arguments
///
/// * `path` - A `PathBuf` representing the file path to which to store data.
async fn store_to_file(&mut self, path: PathBuf) -> Result<()>;

/// Store the recorded measurement.
///
/// This method handles the storage of a new measurement.
async fn new_measurement(&mut self) -> Result<()>;

/// Store the recorded measurement.
///
/// This method handles the storage of the recorded measurement.
async fn store_recorded_measurement(&mut self) -> Result<()>;
}

/// StorageApi trait
///
/// This trait defines the asynchronous API for managing storage operations in the application.
/// It provides methods to interact with the active measurement.
///
/// # Type Parameters
///
/// * `MT` - A type that implements the `MeasurementModelApi` trait.
///
pub trait StorageApi<MT: MeasurementModelApi> {
/// Get the active measurement.
///
/// This method returns a reference to the active measurement, if any.
fn get_active_measurement(&mut self) -> &Option<Arc<RwLock<MT>>>;
}

/// MeasurementApi trait
///
/// This trait extends the `MeasurementModelApi` trait and defines additional asynchronous APIs
/// for mutatung measurement-related operations in the application. It provides methods to set
/// statistical windows, configure outlier filters, and record heart rate messages.
#[async_trait]
pub trait MeasurementApi: MeasurementModelApi {
/// Set the statistics window.
///
/// This method sets the duration of the window used for statistical calculations.
///
/// # Arguments
///
/// * `window` - A `Duration` representing the length of the statistics window.
async fn set_stats_window(&mut self, window: Duration) -> Result<()>;

/// Set the outlier filter.
///
/// This method configures the outlier filter used to process the measurements.
///
/// # Arguments
///
/// * `filter` - An `OutlierFilter` specifying the type and parameters of the filter.
async fn set_outlier_filter(&mut self, filter: OutlierFilter) -> Result<()>;

/// Record a heart rate message.
///
/// This method processes and records a new heart rate message.
///
/// # Arguments
///
/// * `msg` - A `HeartrateMessage` containing the heart rate data to be recorded.
async fn record_message(&mut self, msg: HeartrateMessage) -> Result<()>;
}

/// BluetoothApi trait
///
/// This trait extends the `BluetoothModelApi` trait and defines additional asynchronous APIs
/// for mutating Bluetooth operations in the application. It provides methods to discover adapters,
/// select adapters and peripherals, start and stop scanning, and start and stop listening for
/// Bluetooth events.
#[async_trait]
pub trait BluetoothApi: BluetoothModelApi + Send + Sync {
/// Discover Bluetooth adapters.
///
/// This method initiates the discovery of available Bluetooth adapters.
async fn discover_adapters(&mut self) -> Result<()>;

/// Select a Bluetooth adapter.
///
/// This method selects a Bluetooth adapter based on the provided adapter descriptor.
///
/// # Arguments
///
/// * `adapter` - An `AdapterDescriptor` representing the unique identifier of the adapter to be selected.
async fn select_adapter(&mut self, adapter: AdapterDescriptor) -> Result<()>;

/// Select a Bluetooth peripheral.
///
/// This method selects a Bluetooth peripheral based on the provided device descriptor.
///
/// # Arguments
///
/// * `device` - A `DeviceDescriptor` representing the unique identifier of the peripheral to be selected.
async fn select_peripheral(&mut self, device: DeviceDescriptor) -> Result<()>;

/// Start scanning for Bluetooth devices.
///
/// This method initiates the scanning process to discover Bluetooth peripherals.
async fn start_scan(&mut self) -> Result<()>;

/// Stop scanning for Bluetooth devices.
///
/// This method stops the ongoing scanning process for discovering Bluetooth peripherals.
#[allow(dead_code)]
async fn stop_scan(&mut self) -> Result<()>;

/// Start listening to the last selected bluetooth peripheral
async fn start_listening(&mut self) -> Result<()>;

/// Stop listening to the bluetooth peripheral
async fn stop_listening(&mut self) -> Result<()>;
}

/// AdapterDiscovery trait
///
/// This trait defines the asynchronous API for discovering Bluetooth adapters in the application.
/// It provides a method to discover available Bluetooth adapters.
///
/// # Type Parameters
///
/// * `A` - A type that implements the `Central` and `DisplayName` traits.
///
#[async_trait]
pub trait AdapterDiscovery<A: Central + DisplayName> {
/// Discover Bluetooth adapters.
///
/// This method initiates the discovery of available Bluetooth adapters and returns a vector of adapters.
///
/// # Returns
///
/// A `Result` containing a vector of discovered adapters of type `A` on success, or an error on failure.
async fn discover_adapters() -> Result<Vec<A>>;
}

/// DisplayName trait
///
/// This trait defines the asynchronous API for retrieving the display name of an object.
/// It provides a method to get the name to display for the implementing object.
#[async_trait]
pub trait DisplayName {
/// Get the name to display for the implementing object.
///
/// This method returns the display name of the object as a `String`.
///
/// # Returns
///
/// A `Result` containing the display name of the object as a `String` on success, or an error on failure.
async fn get_name(&self) -> Result<String>;
}
104 changes: 104 additions & 0 deletions src/api/model.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//! This module defines the read only API for interacting with various models.
//! It provides interfaces for accessing data related to HRV measurements,
//! Bluetooth adapters, and stored acquisitions.
use btleplug::api::BDAddr;
use std::{fmt::Debug, sync::Arc};
use time::{Duration, OffsetDateTime};
use tokio::sync::RwLock;

use crate::model::{
bluetooth::{AdapterDescriptor, DeviceDescriptor, HeartrateMessage},
hrv::{HrvSessionData, HrvStatistics},
};

/// `MeasurementModelApi` trait.
///
/// Defines the interface for managing measurement-related data, including runtime measurements,
/// HRV statistics, and stored acquisitions.
pub trait MeasurementModelApi: Debug + Send + Sync {
/// Retrieves the start time of the current acquisition.
///
/// # Returns
/// An `OffsetDateTime` indicating the start time.
fn get_start_time(&self) -> &OffsetDateTime;

/// Retrieves the last heart rate message received.
///
/// # Returns
/// An optional `HeartrateMessage` representing the most recent measurement.
fn get_last_msg(&self) -> Option<&HeartrateMessage>;

/// Retrieves the current HRV statistics.
///
/// # Returns
/// A reference to an optional `HrvStatistics` containing computed HRV data.
fn get_hrv_stats(&self) -> Option<&HrvStatistics>;

/// Retrieves the configured statistics window.
///
/// # Returns
/// A reference to an optional `Duration` representing the analysis window size.
fn get_stats_window(&self) -> Option<&Duration>;

/// Getter for the filter parameter value (fraction of std. dev).
///
/// # Returns
/// The parameter value for the outlier filter.
fn get_outlier_filter_value(&self) -> f64;

/// Retrieves the points for the Poincare plot.
///
/// # Returns
/// A vector of `[f64; 2]` pairs representing the Poincare points.
fn get_poincare_points(&self) -> Vec<[f64; 2]>;

/// Retrieves the session data.
///
/// # Returns
/// A reference to the `HrvSessionData`.
fn get_session_data(&self) -> &HrvSessionData;

/// Retrieves the elapsed time since the start of the acquisition.
///
/// # Returns
/// A `Duration` representing the elapsed time.
fn get_elapsed_time(&self) -> Duration;
}

pub trait BluetoothModelApi: Debug + Send + Sync {
/// Gets the list of Bluetooth adapters as a vector of `(Name, UUID)` tuples.
///
/// # Returns
/// A vector of tuples containing adapter names and UUIDs.
fn get_adapters(&self) -> &[AdapterDescriptor];

/// Gets the currently selected adapter, if any.
///
/// # Returns
/// An optional reference to the selected adapter.
fn get_selected_adapter(&self) -> Option<AdapterDescriptor>;

/// Gets the list of discovered Bluetooth devices.
///
/// # Returns
/// A reference to the vector of devices.
fn get_devices(&self) -> &Arc<RwLock<Vec<DeviceDescriptor>>>;

fn get_selected_device(&self) -> Option<DeviceDescriptor>;

/// Gets the scanning status.
///
/// # Returns
/// `true` if scanning is active, `false` otherwise.
#[allow(dead_code)]
fn is_scanning(&self) -> bool;

fn is_listening_to(&self) -> Option<BDAddr>;
}

pub trait StorageModelApi: Debug + Sync + Send {
/// Returns a slice of handles to the stored acquisition models.
fn get_acquisitions(&self) -> &[ModelHandle<dyn MeasurementModelApi>];
}

pub type ModelHandle<T> = Arc<RwLock<T>>;
4 changes: 2 additions & 2 deletions src/core/view_trait.rs → src/api/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! This module defines the `ViewApi` trait, which is implemented by all views in the HRV analysis tool.
//! It provides a standardized interface for rendering and updating views.
use super::events::UiInputEvent;
use crate::core::events::AppEvent;

/// Trait defining the interface for application views.
///
Expand All @@ -17,7 +17,7 @@ pub trait ViewApi: Send {
///
/// # Returns
/// A result indicating success or failure.
fn render<F: Fn(UiInputEvent) + ?Sized>(
fn render<F: Fn(AppEvent) + ?Sized>(
&mut self,
publish: &F,
ctx: &egui::Context,
Expand Down
Loading

0 comments on commit bc29a9a

Please sign in to comment.