use crate::types::EpicsValue;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
#[repr(u16)]
pub enum AlarmSeverity {
#[default]
NoAlarm = 0,
Minor = 1,
Major = 2,
Invalid = 3,
}
impl AlarmSeverity {
pub fn from_u16(v: u16) -> Self {
match v {
0 => Self::NoAlarm,
1 => Self::Minor,
2 => Self::Major,
3 => Self::Invalid,
_ => Self::Invalid,
}
}
}
#[derive(Clone, Debug)]
pub struct AnalogAlarmConfig {
pub hihi: AlarmLimit,
pub high: AlarmLimit,
pub low: AlarmLimit,
pub lolo: AlarmLimit,
pub hhsv: i16,
pub hsv: i16,
pub lsv: i16,
pub llsv: i16,
}
impl Default for AnalogAlarmConfig {
fn default() -> Self {
Self {
hihi: AlarmLimit::default(),
high: AlarmLimit::default(),
low: AlarmLimit::default(),
lolo: AlarmLimit::default(),
hhsv: 0,
hsv: 0,
lsv: 0,
llsv: 0,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum AlarmLimit {
Double(f64),
Long(i32),
Int64(i64),
}
impl Default for AlarmLimit {
fn default() -> Self {
Self::Double(0.0)
}
}
impl AlarmLimit {
pub fn as_f64(self) -> f64 {
match self {
Self::Double(v) => v,
Self::Long(v) => v as f64,
Self::Int64(v) => v as f64,
}
}
pub fn as_i128(self) -> i128 {
match self {
Self::Double(v) => v as i128,
Self::Long(v) => v as i128,
Self::Int64(v) => v as i128,
}
}
pub fn to_epics_value(self) -> EpicsValue {
match self {
Self::Double(v) => EpicsValue::Double(v),
Self::Long(v) => EpicsValue::Long(v),
Self::Int64(v) => EpicsValue::Int64(v),
}
}
pub fn from_stored(value: &EpicsValue) -> Option<Self> {
match value {
EpicsValue::Int64(v) => Some(Self::Int64(*v)),
EpicsValue::Long(v) => Some(Self::Long(*v)),
other => other.to_f64().map(Self::Double),
}
}
}
impl std::fmt::Display for AlarmLimit {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Double(v) => write!(f, "{v}"),
Self::Long(v) => write!(f, "{v}"),
Self::Int64(v) => write!(f, "{v}"),
}
}
}
pub(crate) fn analog_alarm_range<T>(
val: T,
hyst: T,
lalm: T,
[hihi, lolo, high, low]: [T; 4],
[hhsv, llsv, hsv, lsv]: [i16; 4],
) -> u16
where
T: Copy + PartialOrd + std::ops::Add<Output = T> + std::ops::Sub<Output = T>,
{
if hhsv != 0 && (val >= hihi || (lalm == hihi && val >= hihi - hyst)) {
5
} else if llsv != 0 && (val <= lolo || (lalm == lolo && val <= lolo + hyst)) {
1
} else if hsv != 0 && (val >= high || (lalm == high && val >= high - hyst)) {
4
} else if lsv != 0 && (val <= low || (lalm == low && val <= low + hyst)) {
2
} else {
3
}
}