sat-rs/satrs/src/subsystem.rs
2025-01-23 17:05:19 +01:00

135 lines
4.1 KiB
Rust

use crate::{
mode::{Mode, ModeAndSubmode, ModeRequest, ModeRequestSender},
mode_tree::{SequenceModeTable, SequenceTableMapTable, SequenceTableMapValue},
queue::GenericTargetedMessagingError,
request::RequestId,
ComponentId,
};
#[derive(Debug, PartialEq, Eq)]
pub enum SequenceExecutionHelperStates {
Idle,
AwaitingCheckSuccess,
Done,
}
#[derive(Debug)]
pub struct SequenceExecutionHelper {
target_mode: Mode,
state: SequenceExecutionHelperStates,
request_id: RequestId,
current_sequence_index: Option<usize>,
}
pub trait CheckSuccessProvider {
fn mode_request_requires_success_check(
&mut self,
target_id: ComponentId,
target_mode: ModeAndSubmode,
);
}
#[derive(Debug)]
pub enum SequenceHandlerResult {
SequenceDone,
SequenceStepDone,
AwaitingSuccessCheck,
}
impl SequenceExecutionHelper {
pub fn new(
mode: Mode,
request_id: RequestId,
sequence_table: &SequenceModeTable,
) -> Option<Self> {
if !sequence_table.0.contains_key(&mode) {
return None;
}
Some(Self {
target_mode: mode,
state: SequenceExecutionHelperStates::Idle,
request_id,
current_sequence_index: None,
})
}
pub fn confirm_sequence_done(&mut self) {
if let SequenceExecutionHelperStates::AwaitingCheckSuccess = self.state {
self.state = SequenceExecutionHelperStates::Idle;
}
}
pub fn run(
&mut self,
table: &SequenceModeTable,
sender: &impl ModeRequestSender,
) -> Result<SequenceHandlerResult, GenericTargetedMessagingError> {
if self.state == SequenceExecutionHelperStates::AwaitingCheckSuccess {
return Ok(SequenceHandlerResult::AwaitingSuccessCheck);
}
match self.current_sequence_index {
Some(idx) => {
// Execute the sequence.
let seq_table_value = table.0.get(&self.target_mode).unwrap();
self.execute_sequence_and_map_to_result(seq_table_value, idx, sender)
}
None => {
// Find the first sequence
let seq_table_value = table.0.get(&self.target_mode).unwrap();
if seq_table_value.entries.is_empty() {
Ok(SequenceHandlerResult::SequenceDone)
} else {
self.current_sequence_index = Some(0);
self.execute_sequence_and_map_to_result(seq_table_value, 0, sender)
}
}
}
}
pub fn execute_sequence_and_map_to_result(
&mut self,
seq_table_value: &SequenceTableMapValue,
sequence_idx: usize,
sender: &impl ModeRequestSender,
) -> Result<SequenceHandlerResult, GenericTargetedMessagingError> {
if Self::execute_sequence(
self.request_id,
&seq_table_value.entries[sequence_idx],
sender,
)? {
self.state = SequenceExecutionHelperStates::AwaitingCheckSuccess;
Ok(SequenceHandlerResult::AwaitingSuccessCheck)
} else if seq_table_value.entries.len() - 1 == sequence_idx {
return Ok(SequenceHandlerResult::SequenceDone);
} else {
self.current_sequence_index = Some(sequence_idx + 1);
return Ok(SequenceHandlerResult::SequenceStepDone);
}
}
pub fn execute_sequence(
request_id: RequestId,
map_table: &SequenceTableMapTable,
//sequence_idx: usize,
sender: &impl ModeRequestSender,
) -> Result<bool, GenericTargetedMessagingError> {
let mut some_succes_check_required = false;
for entry in &map_table.entries {
sender.send_mode_request(
request_id,
entry.common.target_id,
ModeRequest::SetMode(entry.common.mode_submode),
)?;
if entry.check_success {
some_succes_check_required = true;
}
}
Ok(some_succes_check_required)
}
}
#[cfg(test)]
mod tests {
pub struct SatSystem {}
}