use bacnet_types::enums::{ObjectType, PropertyIdentifier};
use super::CovReportedProperty;
pub(super) fn cov_reported_properties_default(
object_type: ObjectType,
) -> &'static [CovReportedProperty] {
use CovReportedProperty::{Trigger, Value};
use PropertyIdentifier as P;
match object_type {
ObjectType::ACCESS_DOOR => &[Trigger(P::DOOR_ALARM_STATE)],
ObjectType::ACCESS_POINT => &[
Value(P::ACCESS_EVENT_TAG),
Trigger(P::ACCESS_EVENT_TIME),
Value(P::ACCESS_EVENT_CREDENTIAL),
Value(P::ACCESS_EVENT_AUTHENTICATION_FACTOR),
],
ObjectType::CREDENTIAL_DATA_INPUT => &[Trigger(P::UPDATE_TIME)],
ObjectType::LOAD_CONTROL => &[
Trigger(P::REQUESTED_SHED_LEVEL),
Trigger(P::START_TIME),
Trigger(P::SHED_DURATION),
Trigger(P::DUTY_WINDOW),
],
ObjectType::LOOP => &[Value(P::SETPOINT), Value(P::CONTROLLED_VARIABLE_VALUE)],
ObjectType::PULSE_CONVERTER => &[Value(P::UPDATE_TIME)],
ObjectType::STAGING => &[Trigger(P::PRESENT_STAGE)],
_ => &[],
}
}
#[inline]
pub(super) fn array_property_default(
object_type: ObjectType,
property: PropertyIdentifier,
) -> bool {
use PropertyIdentifier as P;
match property {
P::PROPERTY_LIST
| P::TAGS
| P::OBJECT_LIST
| P::STRUCTURED_OBJECT_LIST
| P::CONFIGURATION_FILES
| P::EVENT_TIME_STAMPS
| P::EVENT_MESSAGE_TEXTS
| P::EVENT_MESSAGE_TEXTS_CONFIG
| P::PRIORITY_ARRAY
| P::COMMAND_TIME_ARRAY
| P::VALUE_SOURCE_ARRAY
| P::STATE_TEXT
| P::PRIORITY
| P::WEEKLY_SCHEDULE
| P::EXCEPTION_SCHEDULE
| P::SHED_LEVELS
| P::SHED_LEVEL_DESCRIPTIONS
| P::SUBORDINATE_LIST
| P::SUBORDINATE_ANNOTATIONS
| P::SUBORDINATE_TAGS
| P::SUBORDINATE_NODE_TYPES
| P::SUBORDINATE_RELATIONSHIPS
| P::DOOR_MEMBERS
| P::ACCESS_DOORS
| P::AUTHENTICATION_POLICY_LIST
| P::AUTHENTICATION_POLICY_NAMES
| P::POSITIVE_ACCESS_RULES
| P::NEGATIVE_ACCESS_RULES
| P::AUTHENTICATION_FACTORS
| P::ASSIGNED_ACCESS_RIGHTS
| P::SUPPORTED_FORMATS
| P::SUPPORTED_FORMAT_CLASSES
| P::BIT_TEXT
| P::GROUP_MEMBERS
| P::GROUP_MEMBER_NAMES
| P::PORT_FILTER
| P::EXECUTION_DELAY
| P::CONTROL_GROUPS
| P::IP_DNS_SERVER
| P::IPV6_DNS_SERVER
| P::LINK_SPEEDS
| P::STATE_CHANGE_VALUES
| P::FLOOR_TEXT
| P::CAR_DOOR_TEXT
| P::CAR_DOOR_STATUS
| P::CAR_DOOR_COMMAND
| P::LANDING_DOOR_STATUS
| P::MAKING_CAR_CALL
| P::REGISTERED_CAR_CALL
| P::ASSIGNED_LANDING_CALLS
| P::STAGES
| P::STAGE_NAMES
| P::TARGET_REFERENCES
| P::MONITORED_OBJECTS => true,
P::ACTION | P::ACTION_TEXT => object_type == ObjectType::COMMAND,
P::ALARM_VALUES | P::FAULT_VALUES => matches!(
object_type,
ObjectType::CHARACTERSTRING_VALUE | ObjectType::BITSTRING_VALUE
),
P::LIST_OF_OBJECT_PROPERTY_REFERENCES => object_type == ObjectType::CHANNEL,
P::LOG_DEVICE_OBJECT_PROPERTY => object_type == ObjectType::TREND_LOG_MULTIPLE,
P::PRESENT_VALUE => object_type == ObjectType::GLOBAL_GROUP,
_ => false,
}
}
#[inline]
pub(super) fn list_property_default(object_type: ObjectType, property: PropertyIdentifier) -> bool {
match property {
PropertyIdentifier::DATE_LIST
| PropertyIdentifier::DEVICE_ADDRESS_BINDING
| PropertyIdentifier::ACTIVE_COV_SUBSCRIPTIONS
| PropertyIdentifier::ACTIVE_COV_MULTIPLE_SUBSCRIPTIONS
| PropertyIdentifier::VT_CLASSES_SUPPORTED
| PropertyIdentifier::ACTIVE_VT_SESSIONS
| PropertyIdentifier::TIME_SYNCHRONIZATION_RECIPIENTS
| PropertyIdentifier::UTC_TIME_SYNCHRONIZATION_RECIPIENTS
| PropertyIdentifier::RESTART_NOTIFICATION_RECIPIENTS
| PropertyIdentifier::LIST_OF_GROUP_MEMBERS
| PropertyIdentifier::RECIPIENT_LIST
| PropertyIdentifier::LOG_BUFFER
| PropertyIdentifier::ACCEPTED_MODES
| PropertyIdentifier::LIFE_SAFETY_ALARM_VALUES
| PropertyIdentifier::ZONE_MEMBERS
| PropertyIdentifier::MASKED_ALARM_VALUES
| PropertyIdentifier::FAILED_ATTEMPT_EVENTS
| PropertyIdentifier::ACCESS_ALARM_EVENTS
| PropertyIdentifier::ACCESS_TRANSACTION_EVENTS
| PropertyIdentifier::CREDENTIALS_IN_ZONE
| PropertyIdentifier::ENTRY_POINTS
| PropertyIdentifier::EXIT_POINTS
| PropertyIdentifier::MEMBERS
| PropertyIdentifier::CREDENTIALS
| PropertyIdentifier::REASON_FOR_DISABLE
| PropertyIdentifier::AUTHORIZATION_EXEMPTIONS
| PropertyIdentifier::COVU_RECIPIENTS
| PropertyIdentifier::SUBSCRIBED_RECIPIENTS
| PropertyIdentifier::BBMD_BROADCAST_DISTRIBUTION_TABLE
| PropertyIdentifier::BBMD_FOREIGN_DEVICE_TABLE
| PropertyIdentifier::MANUAL_SLAVE_ADDRESS_BINDING
| PropertyIdentifier::SLAVE_ADDRESS_BINDING
| PropertyIdentifier::VIRTUAL_MAC_ADDRESS_TABLE
| PropertyIdentifier::ROUTING_TABLE
| PropertyIdentifier::LANDING_CALLS
| PropertyIdentifier::FAULT_SIGNALS => true,
PropertyIdentifier::ALARM_VALUES | PropertyIdentifier::FAULT_VALUES => !matches!(
object_type,
ObjectType::CHARACTERSTRING_VALUE | ObjectType::BITSTRING_VALUE
),
PropertyIdentifier::LIST_OF_OBJECT_PROPERTY_REFERENCES => {
object_type != ObjectType::CHANNEL
}
PropertyIdentifier::PRESENT_VALUE => object_type == ObjectType::GROUP,
PropertyIdentifier::MEMBER_OF => matches!(
object_type,
ObjectType::LIFE_SAFETY_POINT | ObjectType::LIFE_SAFETY_ZONE | ObjectType::ACCESS_USER
),
_ => false,
}
}
#[inline]
pub(super) fn historical_writable_default(
object_type: ObjectType,
property: PropertyIdentifier,
) -> bool {
if property == PropertyIdentifier::OBJECT_IDENTIFIER
|| property == PropertyIdentifier::OBJECT_TYPE
|| property == PropertyIdentifier::PROPERTY_LIST
|| property == PropertyIdentifier::STATUS_FLAGS
{
return false;
}
if property == PropertyIdentifier::OBJECT_NAME {
return true;
}
if property == PropertyIdentifier::PRESENT_VALUE {
return object_type != ObjectType::ANALOG_INPUT
&& object_type != ObjectType::BINARY_INPUT
&& object_type != ObjectType::MULTI_STATE_INPUT;
}
property == PropertyIdentifier::DESCRIPTION
|| property == PropertyIdentifier::OUT_OF_SERVICE
|| property == PropertyIdentifier::COV_INCREMENT
|| property == PropertyIdentifier::HIGH_LIMIT
|| property == PropertyIdentifier::LOW_LIMIT
|| property == PropertyIdentifier::DEADBAND
|| property == PropertyIdentifier::NOTIFICATION_CLASS
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn list_classification_follows_the_datatype_and_never_overlaps_arrays() {
for object_type in (0..=63).map(ObjectType::from_raw) {
for property in (0..=1023).map(PropertyIdentifier::from_raw) {
assert!(
!(array_property_default(object_type, property)
&& list_property_default(object_type, property)),
"{object_type:?} {property:?} is both an array and a list"
);
}
}
let cases = [
(ObjectType::CALENDAR, PropertyIdentifier::DATE_LIST, true),
(
ObjectType::NOTIFICATION_CLASS,
PropertyIdentifier::RECIPIENT_LIST,
true,
),
(
ObjectType::ELEVATOR_GROUP,
PropertyIdentifier::LANDING_CALLS,
true,
),
(
ObjectType::MULTI_STATE_INPUT,
PropertyIdentifier::ALARM_VALUES,
true,
),
(
ObjectType::CHARACTERSTRING_VALUE,
PropertyIdentifier::ALARM_VALUES,
false,
),
(
ObjectType::BITSTRING_VALUE,
PropertyIdentifier::ALARM_VALUES,
false,
),
(
ObjectType::SCHEDULE,
PropertyIdentifier::LIST_OF_OBJECT_PROPERTY_REFERENCES,
true,
),
(
ObjectType::CHANNEL,
PropertyIdentifier::LIST_OF_OBJECT_PROPERTY_REFERENCES,
false,
),
(ObjectType::GROUP, PropertyIdentifier::PRESENT_VALUE, true),
(
ObjectType::GLOBAL_GROUP,
PropertyIdentifier::PRESENT_VALUE,
false,
),
(
ObjectType::DATETIME_VALUE,
PropertyIdentifier::PRESENT_VALUE,
false,
),
(
ObjectType::LIFE_SAFETY_ZONE,
PropertyIdentifier::MEMBER_OF,
true,
),
(ObjectType::AUDIT_LOG, PropertyIdentifier::MEMBER_OF, false),
(
ObjectType::ELEVATOR_GROUP,
PropertyIdentifier::LANDING_CALL_CONTROL,
false,
),
(
ObjectType::MULTI_STATE_VALUE,
PropertyIdentifier::STATE_TEXT,
false,
),
(ObjectType::DEVICE, PropertyIdentifier::OBJECT_LIST, false),
(ObjectType::DEVICE, PropertyIdentifier::PROPERTY_LIST, false),
];
for (object_type, property, list) in cases {
assert_eq!(
list_property_default(object_type, property),
list,
"{object_type:?} {property:?}"
);
}
}
}