use bacnet_types::enums::{DoorAlarmState, PropertyIdentifier, Reliability};
use bacnet_types::error::Error;
use bacnet_types::primitives::PropertyValue;
use super::door_out_of_service::door_alarm_state_in_range;
use crate::event::state_reporting::{
checked_raw_list, enumerated_list, enumerated_list_value, ListedStates,
};
#[derive(Debug, Clone, Default)]
pub(super) struct DoorAlarmLists {
fault_values: Vec<u32>,
masked_alarm_values: Vec<u32>,
}
impl DoorAlarmLists {
pub(super) fn admits(&self, alarm_values: &[u32], state: DoorAlarmState) -> bool {
let raw = state.to_raw();
!self.masked_alarm_values.contains(&raw)
&& (state == DoorAlarmState::NORMAL
|| alarm_values.contains(&raw)
|| self.fault_values.contains(&raw))
}
pub(super) fn fault_state(&self, state: DoorAlarmState) -> Reliability {
if self.fault_values.contains(&state.to_raw()) {
Reliability::MULTI_STATE_FAULT
} else {
Reliability::NO_FAULT_DETECTED
}
}
pub(super) fn masks_any(&self) -> bool {
!self.masked_alarm_values.is_empty()
}
pub(super) fn set_fault_values(&mut self, values: Vec<u32>) -> Result<(), Error> {
self.fault_values = checked_raw_list(values, LISTED_STATES)?;
Ok(())
}
pub(super) fn set_masked_alarm_values(&mut self, values: Vec<u32>) -> Result<(), Error> {
self.masked_alarm_values = checked_raw_list(values, LISTED_STATES)?;
Ok(())
}
pub(super) fn read(&self, property: PropertyIdentifier) -> Option<PropertyValue> {
match property {
p if p == PropertyIdentifier::FAULT_VALUES => {
Some(enumerated_list_value(&self.fault_values))
}
p if p == PropertyIdentifier::MASKED_ALARM_VALUES => {
Some(enumerated_list_value(&self.masked_alarm_values))
}
_ => None,
}
}
pub(super) fn write(
&mut self,
property: PropertyIdentifier,
array_index: Option<u32>,
value: &PropertyValue,
) -> Option<Result<(), Error>> {
let list = match property {
p if p == PropertyIdentifier::FAULT_VALUES => &mut self.fault_values,
p if p == PropertyIdentifier::MASKED_ALARM_VALUES => &mut self.masked_alarm_values,
_ => return None,
};
Some(enumerated_list(array_index, value, LISTED_STATES).map(|values| *list = values))
}
}
pub(super) const LISTED_STATES: ListedStates = ListedStates {
normal: DoorAlarmState::NORMAL.to_raw(),
in_range: |raw| door_alarm_state_in_range(DoorAlarmState::from_raw(raw)),
};