use crate::flags::MotorCommand;
use asyn_rs::interfaces::motor::MotorStatus;
use std::sync::{Arc, Mutex};
use std::time::Duration;
#[derive(Debug, Clone)]
pub struct StampedStatus {
pub seq: u64,
pub status: MotorStatus,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum PollDirective {
#[default]
None,
Start,
Stop,
}
#[derive(Debug, Clone)]
pub struct DelayRequest {
pub id: u64,
pub duration: Duration,
}
#[derive(Debug, Default)]
pub struct DeviceActions {
pub commands: Vec<MotorCommand>,
pub poll: PollDirective,
pub schedule_delay: Option<DelayRequest>,
pub status_refresh: bool,
}
impl DeviceActions {
pub fn merge_newer(&mut self, newer: DeviceActions) {
self.commands.extend(newer.commands);
if newer.poll != PollDirective::None {
self.poll = newer.poll;
}
if newer.schedule_delay.is_some() {
self.schedule_delay = newer.schedule_delay;
}
self.status_refresh |= newer.status_refresh;
}
}
#[derive(Debug)]
pub struct MotorDeviceState {
pub latest_status: Option<StampedStatus>,
pub expired_delay_id: Option<u64>,
pub pending_actions: Option<DeviceActions>,
}
impl Default for MotorDeviceState {
fn default() -> Self {
Self {
latest_status: None,
expired_delay_id: None,
pending_actions: None,
}
}
}
pub type SharedDeviceState = Arc<Mutex<MotorDeviceState>>;
pub fn new_shared_state() -> SharedDeviceState {
Arc::new(Mutex::new(MotorDeviceState::default()))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn merge_newer_appends_commands_fifo() {
let mut a = DeviceActions {
commands: vec![MotorCommand::Stop { acceleration: 1.0 }],
..Default::default()
};
let b = DeviceActions {
commands: vec![MotorCommand::Poll],
..Default::default()
};
a.merge_newer(b);
assert_eq!(a.commands.len(), 2);
assert!(matches!(a.commands[0], MotorCommand::Stop { .. }));
assert!(matches!(a.commands[1], MotorCommand::Poll));
}
#[test]
fn merge_newer_poll_none_keeps_previous() {
let mut a = DeviceActions {
poll: PollDirective::Start,
..Default::default()
};
let b = DeviceActions {
poll: PollDirective::None,
..Default::default()
};
a.merge_newer(b);
assert_eq!(a.poll, PollDirective::Start);
}
#[test]
fn merge_newer_poll_explicit_overrides() {
let mut a = DeviceActions {
poll: PollDirective::Start,
..Default::default()
};
let b = DeviceActions {
poll: PollDirective::Stop,
..Default::default()
};
a.merge_newer(b);
assert_eq!(a.poll, PollDirective::Stop);
}
#[test]
fn merge_newer_takes_newer_delay_and_refresh() {
let mut a = DeviceActions::default();
let b = DeviceActions {
schedule_delay: Some(DelayRequest {
id: 7,
duration: Duration::from_millis(5),
}),
status_refresh: true,
..Default::default()
};
a.merge_newer(b);
assert_eq!(a.schedule_delay.as_ref().unwrap().id, 7);
assert!(a.status_refresh);
}
}