mirror of
https://github.com/hubaldv/bioz-host-rs.git
synced 2026-07-24 00:57:44 +00:00
Major commit adding a control layer in between for later TCP use.
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -3,14 +3,16 @@ use std::time::SystemTime;
|
||||
use log::{error, info};
|
||||
|
||||
use tokio::select;
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
use tokio::sync::{watch, mpsc::{Receiver, Sender}};
|
||||
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
use atomic_float::AtomicF32;
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use bioz_icd_rs::{MeasurementPointSet, MultiplexerCapability};
|
||||
use bioz_icd_rs::{SweepPoints, MultiplexerCapability};
|
||||
|
||||
use crate::state::{HardwareState, MeasurementDataState};
|
||||
|
||||
use crate::icd;
|
||||
use crate::client::WorkbookClient;
|
||||
@@ -20,29 +22,24 @@ use crate::plot::{TimeSeriesPlot, BodePlot};
|
||||
|
||||
use crate::signals::{LoggingSignal, StartStopSignal};
|
||||
|
||||
use crate::app::HardwareConnected;
|
||||
use crate::state::HardwareConnected;
|
||||
|
||||
pub async fn communicate_with_hardware(
|
||||
mut run_impedancemeter_rx: Receiver<StartStopSignal>,
|
||||
run_impedancemeter_tx: Sender<StartStopSignal>,
|
||||
magnitude: Arc<Mutex<f32>>,
|
||||
phase: Arc<Mutex<f32>>,
|
||||
magnitude_series: Arc<Mutex<TimeSeriesPlot>>,
|
||||
phase_series: Arc<Mutex<TimeSeriesPlot>>,
|
||||
bode_series: Arc<Mutex<BodePlot>>,
|
||||
connected: Arc<Mutex<HardwareConnected>>,
|
||||
data_frequency: Arc<AtomicF32>,
|
||||
periods_per_dft: Arc<Mutex<Option<f32>>>,
|
||||
periods_per_dft_sweep: Arc<Mutex<(Vec<u32>, Option<Vec<f32>>)>>,
|
||||
measurement_data: Arc<MeasurementDataState>,
|
||||
hardware_state_tx: watch::Sender<HardwareState>,
|
||||
gui_logging_state: Arc<Mutex<LoggingStates>>,
|
||||
log_tx: Sender<LoggingSignal>,
|
||||
) {
|
||||
let data_counter = Arc::new(AtomicU32::new(0));
|
||||
let data_counter_clone = data_counter.clone();
|
||||
let sampling_rate_clone = measurement_data.sampling_rate.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
|
||||
data_frequency.store(data_counter.load(Ordering::Relaxed) as f32, Ordering::Relaxed);
|
||||
sampling_rate_clone.store(data_counter.load(Ordering::Relaxed) as f32, Ordering::Relaxed);
|
||||
data_counter.store(0, Ordering::Relaxed);
|
||||
}
|
||||
});
|
||||
@@ -54,6 +51,8 @@ pub async fn communicate_with_hardware(
|
||||
let settings = Arc::new(Mutex::new(Settings::default()));
|
||||
|
||||
loop {
|
||||
let mut hardware_state = HardwareState::default();
|
||||
|
||||
let workbook_client = match WorkbookClient::new() {
|
||||
Ok(client) => {
|
||||
info!("Connected to hardware successfully.");
|
||||
@@ -62,11 +61,13 @@ pub async fn communicate_with_hardware(
|
||||
}
|
||||
match client.get_device_info().await.unwrap() {
|
||||
MultiplexerCapability::Absent => {
|
||||
*connected.lock().unwrap() = HardwareConnected::WithoutMultiplexer;
|
||||
hardware_state.connected = HardwareConnected::WithoutMultiplexer;
|
||||
hardware_state_tx.send(hardware_state.clone()).unwrap();
|
||||
info!("Connected device: Without Multiplexer");
|
||||
},
|
||||
MultiplexerCapability::Present => {
|
||||
*connected.lock().unwrap() = HardwareConnected::WithMultiplexer;
|
||||
hardware_state.connected = HardwareConnected::WithMultiplexer;
|
||||
hardware_state_tx.send(hardware_state.clone()).unwrap();
|
||||
info!("Connected device: With Multiplexer");
|
||||
},
|
||||
}
|
||||
@@ -86,7 +87,7 @@ pub async fn communicate_with_hardware(
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let data = (magnitude_series.clone(), phase_series.clone(), magnitude.clone(), phase.clone());
|
||||
let data = (measurement_data.magnitude_series.clone(), measurement_data.phase_series.clone(), measurement_data.magnitude.clone(), measurement_data.phase.clone());
|
||||
let data_counter_clone_single = data_counter_clone.clone();
|
||||
|
||||
// Clone log_tx for the task
|
||||
@@ -139,7 +140,7 @@ pub async fn communicate_with_hardware(
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let data = bode_series.clone();
|
||||
let data = measurement_data.bode_plot.clone();
|
||||
let data_counter_clone_sweep = data_counter_clone.clone();
|
||||
|
||||
// Clone log_tx for the task
|
||||
@@ -151,30 +152,30 @@ pub async fn communicate_with_hardware(
|
||||
|
||||
match val.points {
|
||||
|
||||
MeasurementPointSet::Eight => {
|
||||
SweepPoints::Eight => {
|
||||
let magnitudes: Vec<f32> = val.magnitudes_8.into_iter().collect();
|
||||
let phases: Vec<f32> = val.phases_8.into_iter().collect();
|
||||
{
|
||||
let mut bode_plot = data.lock().unwrap();
|
||||
bode_plot.update_magnitudes(MeasurementPointSet::Eight, magnitudes.clone());
|
||||
bode_plot.update_phases(MeasurementPointSet::Eight, phases.clone());
|
||||
bode_plot.update_magnitudes(SweepPoints::Eight, magnitudes.clone());
|
||||
bode_plot.update_phases(SweepPoints::Eight, phases.clone());
|
||||
}
|
||||
if *gui_logging_state_clone.lock().unwrap() == LoggingStates::Logging {
|
||||
if let Err(e) = log_tx_clone.send(LoggingSignal::SweepImpedance(SystemTime::now(), MeasurementPointSet::Eight.values().to_vec(), magnitudes.clone(), phases.clone())).await {
|
||||
if let Err(e) = log_tx_clone.send(LoggingSignal::SweepImpedance(SystemTime::now(), SweepPoints::Eight.values().to_vec(), magnitudes.clone(), phases.clone())).await {
|
||||
error!("Failed to send logging signal: {:?}", e);
|
||||
}
|
||||
}
|
||||
},
|
||||
MeasurementPointSet::Eighteen => {
|
||||
SweepPoints::Eighteen => {
|
||||
let magnitudes: Vec<f32> = val.magnitudes_18.into_iter().collect();
|
||||
let phases: Vec<f32> = val.phases_18.into_iter().collect();
|
||||
{
|
||||
let mut bode_plot = data.lock().unwrap();
|
||||
bode_plot.update_magnitudes(MeasurementPointSet::Eighteen, magnitudes.clone());
|
||||
bode_plot.update_phases(MeasurementPointSet::Eighteen, phases.clone());
|
||||
bode_plot.update_magnitudes(SweepPoints::Eighteen, magnitudes.clone());
|
||||
bode_plot.update_phases(SweepPoints::Eighteen, phases.clone());
|
||||
}
|
||||
if *gui_logging_state_clone.lock().unwrap() == LoggingStates::Logging {
|
||||
if let Err(e) = log_tx_clone.send(LoggingSignal::SweepImpedance(SystemTime::now(), MeasurementPointSet::Eighteen.values().to_vec(), magnitudes.clone(), phases.clone())).await {
|
||||
if let Err(e) = log_tx_clone.send(LoggingSignal::SweepImpedance(SystemTime::now(), SweepPoints::Eighteen.values().to_vec(), magnitudes.clone(), phases.clone())).await {
|
||||
error!("Failed to send logging signal: {:?}", e);
|
||||
}
|
||||
}
|
||||
@@ -195,7 +196,8 @@ pub async fn communicate_with_hardware(
|
||||
Ok(Ok(periods)) => {
|
||||
info!("Impedance meter started at frequency: {} with periods per DFT: {}", freq, periods);
|
||||
settings.lock().unwrap().mode = Some(StartStopSignal::StartSingle(freq, lead_mode, electrode_config, dft_num));
|
||||
*periods_per_dft.lock().unwrap() = Some(periods);
|
||||
hardware_state.periods_per_dft = Some(periods);
|
||||
hardware_state_tx.send(hardware_state.clone()).unwrap();
|
||||
|
||||
// When logging add electrode configuration to logging file
|
||||
if *gui_logging_state.lock().unwrap() == LoggingStates::Logging {
|
||||
@@ -206,11 +208,13 @@ pub async fn communicate_with_hardware(
|
||||
},
|
||||
Ok(Err(e)) => {
|
||||
error!("Failed to init on hardware: {:?}", e);
|
||||
*periods_per_dft.lock().unwrap() = None;
|
||||
hardware_state.periods_per_dft = None;
|
||||
hardware_state_tx.send(hardware_state.clone()).unwrap();
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Communication error when starting impedancemeter: {:?}", e);
|
||||
*periods_per_dft.lock().unwrap() = None;
|
||||
hardware_state.periods_per_dft = None;
|
||||
hardware_state_tx.send(hardware_state.clone()).unwrap();
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -220,11 +224,14 @@ pub async fn communicate_with_hardware(
|
||||
settings.lock().unwrap().mode = Some(StartStopSignal::StartSweep(lead_mode, electrode_config, num_points));
|
||||
info!("Sweep Impedancemeter started.");
|
||||
match num_points {
|
||||
MeasurementPointSet::Eight => {
|
||||
*periods_per_dft_sweep.lock().unwrap() = (num_points.values().iter().copied().collect(), Some(periods.periods_per_dft_8.into_iter().collect()));
|
||||
SweepPoints::Eight => {
|
||||
hardware_state.periods_per_dft_sweep = (num_points.values().iter().copied().collect(), Some(periods.periods_per_dft_8.into_iter().collect()));
|
||||
hardware_state_tx.send(hardware_state.clone()).unwrap();
|
||||
|
||||
},
|
||||
MeasurementPointSet::Eighteen => {
|
||||
*periods_per_dft_sweep.lock().unwrap() = (num_points.values().iter().copied().collect(), Some(periods.periods_per_dft_18.into_iter().collect()));
|
||||
SweepPoints::Eighteen => {
|
||||
hardware_state.periods_per_dft_sweep = (num_points.values().iter().copied().collect(), Some(periods.periods_per_dft_18.into_iter().collect()));
|
||||
hardware_state_tx.send(hardware_state.clone()).unwrap();
|
||||
},
|
||||
}
|
||||
|
||||
@@ -237,11 +244,13 @@ pub async fn communicate_with_hardware(
|
||||
},
|
||||
Ok(Err(e)) => {
|
||||
error!("Failed to sweep-init on hardware: {:?}", e);
|
||||
*periods_per_dft_sweep.lock().unwrap() = (num_points.values().iter().copied().collect(), None);
|
||||
hardware_state.periods_per_dft_sweep = (num_points.values().iter().copied().collect(), None);
|
||||
hardware_state_tx.send(hardware_state.clone()).unwrap();
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Communication error when starting impedancemeter: {:?}", e);
|
||||
*periods_per_dft_sweep.lock().unwrap() = (num_points.values().iter().copied().collect(), None);
|
||||
hardware_state.periods_per_dft_sweep = (num_points.values().iter().copied().collect(), None);
|
||||
hardware_state_tx.send(hardware_state.clone()).unwrap();
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -250,9 +259,10 @@ pub async fn communicate_with_hardware(
|
||||
error!("Failed to stop impedancemeter: {:?}", e);
|
||||
} else {
|
||||
settings.lock().unwrap().mode = Some(StartStopSignal::Stop);
|
||||
*periods_per_dft.lock().unwrap() = None;
|
||||
let (freq, _) = periods_per_dft_sweep.lock().unwrap().clone();
|
||||
*periods_per_dft_sweep.lock().unwrap() = (freq, None);
|
||||
hardware_state.periods_per_dft = None;
|
||||
let (freq, _) = hardware_state.periods_per_dft_sweep.clone();
|
||||
hardware_state.periods_per_dft_sweep = (freq, None);
|
||||
hardware_state_tx.send(hardware_state.clone()).unwrap();
|
||||
info!("Impedancemeter stopped.");
|
||||
}
|
||||
},
|
||||
@@ -272,7 +282,8 @@ pub async fn communicate_with_hardware(
|
||||
}
|
||||
}
|
||||
info!("Communication with hardware ended.");
|
||||
*connected.lock().unwrap() = HardwareConnected::None;
|
||||
hardware_state.connected = HardwareConnected::None;
|
||||
hardware_state_tx.send(hardware_state).unwrap();
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user