use bacnet_types::enums::{LiftCarDirection, LiftCarDriveStatus, LiftCarMode, PropertyIdentifier};
use bacnet_types::error::Error;
use bacnet_types::primitives::PropertyValue;
use super::{checked, direction_in_range, named_or_proprietary};
use crate::common;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) struct CarState {
pub(super) assigned_direction: LiftCarDirection,
pub(super) door_zone: bool,
pub(super) mode: LiftCarMode,
pub(super) next_stopping_floor: u8,
pub(super) drive_status: LiftCarDriveStatus,
}
pub(super) fn mode_in_range(mode: &LiftCarMode) -> bool {
named_or_proprietary(LiftCarMode::ALL_NAMED, *mode, mode.to_raw())
}
pub(super) fn drive_status_in_range(status: &LiftCarDriveStatus) -> bool {
named_or_proprietary(LiftCarDriveStatus::ALL_NAMED, *status, status.to_raw())
}
impl CarState {
pub(super) fn new() -> Self {
Self {
assigned_direction: LiftCarDirection::UNKNOWN,
door_zone: false,
mode: LiftCarMode::UNKNOWN,
next_stopping_floor: 1,
drive_status: LiftCarDriveStatus::UNKNOWN,
}
}
pub(super) fn read(&self, property: PropertyIdentifier) -> Option<PropertyValue> {
Some(match property {
PropertyIdentifier::CAR_ASSIGNED_DIRECTION => {
PropertyValue::Enumerated(self.assigned_direction.to_raw())
}
PropertyIdentifier::CAR_DOOR_ZONE => PropertyValue::Boolean(self.door_zone),
PropertyIdentifier::CAR_MODE => PropertyValue::Enumerated(self.mode.to_raw()),
PropertyIdentifier::NEXT_STOPPING_FLOOR => {
PropertyValue::Unsigned(self.next_stopping_floor.into())
}
PropertyIdentifier::CAR_DRIVE_STATUS => {
PropertyValue::Enumerated(self.drive_status.to_raw())
}
_ => return None,
})
}
pub(super) fn write(
&mut self,
property: PropertyIdentifier,
value: &PropertyValue,
out_of_service: bool,
) -> Option<Result<(), Error>> {
self.read(property)?;
if !out_of_service {
return Some(Err(common::write_access_denied_error()));
}
Some(self.store(property, value))
}
fn store(&mut self, property: PropertyIdentifier, value: &PropertyValue) -> Result<(), Error> {
match (property, value) {
(PropertyIdentifier::CAR_ASSIGNED_DIRECTION, &PropertyValue::Enumerated(raw)) => {
self.assigned_direction =
checked(LiftCarDirection::from_raw(raw), direction_in_range)?;
}
(PropertyIdentifier::CAR_DOOR_ZONE, &PropertyValue::Boolean(zone)) => {
self.door_zone = zone;
}
(PropertyIdentifier::CAR_MODE, &PropertyValue::Enumerated(raw)) => {
self.mode = checked(LiftCarMode::from_raw(raw), mode_in_range)?;
}
(PropertyIdentifier::NEXT_STOPPING_FLOOR, &PropertyValue::Unsigned(floor)) => {
self.next_stopping_floor =
u8::try_from(floor).map_err(|_| common::value_out_of_range_error())?;
}
(PropertyIdentifier::CAR_DRIVE_STATUS, &PropertyValue::Enumerated(raw)) => {
self.drive_status =
checked(LiftCarDriveStatus::from_raw(raw), drive_status_in_range)?;
}
_ => return Err(common::invalid_data_type_error()),
}
Ok(())
}
}