Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arm debounce #66

Merged
merged 6 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/comms/meb/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use self::response::Statuses;

use anyhow::Result;
use itertools::Itertools;

Check warning

Code scanning / clippy

unused import: itertools::Itertools Warning

unused import: itertools::Itertools
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why cargo is saying this is unused. On line 168, the all_equal() is a part of this import, and the build breaks when I remove the import. Does anyone know why or should we dismiss it?

use tokio::io::AsyncReadExt;
use tokio_serial::{DataBits, Parity, SerialStream, StopBits};

use self::response::Statuses;

pub mod response;

#[derive(Debug)]
Expand All @@ -13,8 +14,8 @@

impl MainElectronicsBoard {
pub async fn new<T>(read_connection: T) -> Self
where
T: 'static + AsyncReadExt + Unpin + Send,
where
T: 'static + AsyncReadExt + Unpin + Send,
{
Self {
statuses: Statuses::new(read_connection).await,
Expand Down
99 changes: 90 additions & 9 deletions src/comms/meb/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
mpsc::{channel, Sender, TryRecvError},
Arc,
},
time::Duration,
};

use crate::{
Expand All @@ -13,10 +12,10 @@

use derive_getters::Getters;
use futures::{stream, StreamExt};
use itertools::Itertools;
use tokio::{
io::{stderr, AsyncReadExt, AsyncWriteExt},
sync::{Mutex, RwLock},
time::sleep,
};

type Lock<T> = Arc<RwLock<Option<T>>>;
Expand All @@ -34,6 +33,7 @@
humid: Lock<[u8; 4]>,
leak: Lock<bool>,
thruster_arm: Lock<bool>,
tarm_count: Arc<Mutex<Vec<bool>>>,
system_voltage: Lock<[u8; 4]>,
shutdown: Lock<u8>,
_tx: Sender<()>,
Expand All @@ -50,7 +50,8 @@
let temp: Lock<_> = Arc::default();
let humid: Lock<_> = Arc::default();
let leak: Lock<_> = Arc::default();
let thruster_arm: Lock<_> = Arc::default();
let thruster_arm: Lock<_> = Arc::new(RwLock::new(Some(false)));
let tarm_count: Arc<Mutex<Vec<bool>>> = Arc::new(Mutex::new(vec![false; 24]));
let system_voltage: Lock<_> = Arc::default();
let shutdown: Lock<_> = Arc::default();
let (_tx, rx) = channel::<()>(); // Signals struct destruction to thread
Expand All @@ -59,6 +60,7 @@
let humid_clone = humid.clone();
let leak_clone = leak.clone();
let thruster_arm_clone = thruster_arm.clone();
let tarm_count_clone = tarm_count.clone();
let system_voltage_clone = system_voltage.clone();
let shutdown_clone = shutdown.clone();

Expand All @@ -74,6 +76,7 @@
&humid_clone,
&leak_clone,
&thruster_arm_clone,
&tarm_count_clone,
&system_voltage_clone,
&shutdown_clone,
&mut stderr(),
Expand All @@ -87,6 +90,7 @@
humid,
leak,
thruster_arm,
tarm_count,
system_voltage,
shutdown,
_tx,
Expand All @@ -103,6 +107,7 @@
humid: &RwLock<Option<[u8; 4]>>,
leak: &RwLock<Option<bool>>,
tarm: &Arc<RwLock<Option<bool>>>,
tarm_count: &Arc<Mutex<Vec<bool>>>,
vsys: &RwLock<Option<[u8; 4]>>,
sdown: &RwLock<Option<u8>>,
err_stream: &mut U,
Expand Down Expand Up @@ -131,12 +136,10 @@
} else if message_body.get(0..4) == Some(&LEAK) {
*leak.write().await = Some(message_body[4] == 1);
} else if message_body.get(0..4) == Some(&TARM) {
let tarm_clone = tarm.clone();
let tarm_status = Some(message_body[4] == 1);
tokio::spawn(async move {
sleep(Duration::from_millis(3500)).await;
*tarm_clone.write().await = tarm_status;
});
let tarm_status = Self::arm_debounce(tarm_count, Some(message_body[4] == 1)).await;
if tarm_status.is_some() {
*tarm.write().await = tarm_status;
}
} else if message_body.get(0..4) == Some(&VSYS) {
*vsys.write().await = Some(message_body[4..].try_into().unwrap());
} else if message_body.get(0..4) == Some(&SDOWN) {
Expand All @@ -155,4 +158,82 @@
}
}).await;
}

async fn arm_debounce(tarm_count: &Arc<Mutex<Vec<bool>>>, current_tarm: Option<bool>) -> Option<bool> {
let mut locked_tarm_count = tarm_count.lock().await;

locked_tarm_count.push(current_tarm.unwrap_or(false));
locked_tarm_count.remove(0);

if locked_tarm_count.iter().all_equal() {
Some(*locked_tarm_count.get(0).unwrap())
Fixed Show fixed Hide fixed
} else {
None
}
}
}


#[cfg(test)]
mod test {
use super::*;

async fn update_tarm(statuses: &Statuses, current_tarm: Option<bool>) {
let tarm_status = Statuses::arm_debounce(&statuses.tarm_count.clone(), current_tarm).await;

if tarm_status.is_some() {
*statuses.thruster_arm.write().await = tarm_status;
}
}
#[tokio::test]
async fn thruster_is_armed() {
let statuses = Statuses::new(tokio::io::empty()).await;

// Receive 24 consecutive messages with thruster arm set to true
for _ in 0..24 {
update_tarm(&statuses, Some(true)).await;
}

assert_eq!(*statuses.thruster_arm.read().await, Some(true));
}

#[tokio::test]
async fn thruster_is_not_armed() {
let statuses = Statuses::new(tokio::io::empty()).await;

// Receive 24 consecutive messages with thruster arm set to true
for _ in 0..24 {
update_tarm(&statuses, Some(false)).await;
}

assert_eq!(*statuses.thruster_arm.read().await, Some(false));
}

#[tokio::test]
async fn thrust_arm_debounce() {
let statuses = Statuses::new(tokio::io::empty()).await;

update_tarm(&statuses, Some(false)).await;
assert_eq!(*statuses.thruster_arm.read().await, Some(false));

for _ in 0..23 {
update_tarm(&statuses, Some(true)).await;
}
assert_eq!(*statuses.thruster_arm.read().await, Some(false));

for _ in 0..1 {
update_tarm(&statuses, Some(true)).await;
}
assert_eq!(*statuses.thruster_arm.read().await, Some(true));

for _ in 0..23 {
update_tarm(&statuses, Some(false)).await;
}
assert_eq!(*statuses.thruster_arm.read().await, Some(true));

for _ in 0..1 {
update_tarm(&statuses, Some(false)).await;
}
assert_eq!(*statuses.thruster_arm.read().await, Some(false));
}
}
3 changes: 2 additions & 1 deletion tests/comms/meb/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{str::from_utf8, sync::Arc};

use sw8s_rust_lib::comms::{auv_control_board::response::find_end, meb::response::Statuses};
use tokio::sync::RwLock;
use tokio::sync::{Mutex, RwLock};

#[tokio::test]
async fn real_comms_read_no_error() {
Expand All @@ -23,6 +23,7 @@ async fn real_comms_read_no_error() {
&RwLock::default(),
&RwLock::default(),
&Arc::default(),
&Arc::new(Mutex::new(vec![false; 24])),
&RwLock::default(),
&RwLock::default(),
&mut err_msg,
Expand Down