eva-robots 0.1.7

Commons for EVA ICS v4
Documentation
use eva_common::prelude::*;
use serde::Serialize;
use std::time::Duration;
use uuid::Uuid;

#[derive(Serialize)]
pub struct Sequence<'a> {
    pub u: Uuid,
    pub seq: Vec<SequenceEntry<'a>>,
    pub on_abort: Option<SequenceActionEntry<'a>>,
    #[serde(serialize_with = "eva_common::tools::serialize_duration_as_micros")]
    pub timeout: Duration,
}

impl<'a> Sequence<'a> {
    #[inline]
    pub fn new(timeout: Duration) -> Self {
        Self {
            u: Uuid::new_v4(),
            seq: <_>::default(),
            on_abort: <_>::default(),
            timeout,
        }
    }
    #[inline]
    pub fn uuid(&self) -> Uuid {
        self.u
    }
    #[inline]
    pub fn timeout(&self) -> Duration {
        self.timeout
    }
    #[inline]
    #[allow(clippy::cast_possible_truncation)]
    pub fn push_delay(&mut self, delay: Duration) {
        self.seq
            .push(SequenceEntry::Delay(delay.as_micros() as u64));
    }
    #[inline]
    pub fn push_action(&mut self, action: SequenceAction<'a>) {
        self.seq
            .push(SequenceEntry::Actions(SequenceActionEntry::Single(action)));
    }
    #[inline]
    pub fn push_actions_multi(&mut self, actions: Vec<SequenceAction<'a>>) {
        self.seq
            .push(SequenceEntry::Actions(SequenceActionEntry::Multi(actions)));
    }
    pub fn max_expected_duration(&self) -> Duration {
        let mut duration: Duration = Duration::from_secs(0);
        for s in &self.seq {
            match s {
                SequenceEntry::Delay(d) => duration += Duration::from_micros(*d),
                SequenceEntry::Actions(a) => match a {
                    SequenceActionEntry::Single(action) => duration += action.wait,
                    SequenceActionEntry::Multi(actions) => {
                        duration += actions.iter().map(|a| a.wait).max().unwrap_or_default();
                    }
                },
            }
        }
        duration
    }
    #[inline]
    pub fn set_on_abort(&mut self, action: SequenceAction<'a>) {
        self.on_abort = Some(SequenceActionEntry::Single(action));
    }
    #[inline]
    pub fn set_on_abort_multi(&mut self, actions: Vec<SequenceAction<'a>>) {
        self.on_abort = Some(SequenceActionEntry::Multi(actions));
    }
    pub fn abort_timeout(&self) -> Duration {
        if let Some(ref on_abort) = self.on_abort {
            match on_abort {
                SequenceActionEntry::Single(a) => a.wait,
                SequenceActionEntry::Multi(actions) => {
                    actions.iter().map(|a| a.wait).max().unwrap_or_default()
                }
            }
        } else {
            Duration::from_secs(0)
        }
    }
}

#[derive(Serialize)]
#[serde(untagged)]
pub enum SequenceEntry<'a> {
    Delay(u64),
    Actions(SequenceActionEntry<'a>),
}

#[derive(Serialize)]
#[serde(untagged)]
pub enum SequenceActionEntry<'a> {
    Single(SequenceAction<'a>),
    Multi(Vec<SequenceAction<'a>>),
}

#[derive(Serialize)]
pub struct SequenceAction<'a> {
    #[serde(rename = "i")]
    pub oid: &'a OID,
    pub params: Option<eva_common::actions::Params>,
    #[serde(serialize_with = "eva_common::tools::serialize_duration_as_micros")]
    pub wait: Duration,
}

impl<'a> SequenceAction<'a> {
    pub fn new_unit(
        oid: &'a OID,
        status: ItemStatus,
        value: Option<Value>,
        wait: Duration,
    ) -> Self {
        Self {
            oid,
            params: Some(eva_common::actions::Params::Unit(
                eva_common::actions::UnitParams {
                    status,
                    value: value.into(),
                },
            )),
            wait,
        }
    }
}