use super::{IpConfig, NetworkPortObject};
use crate::property_metadata::{
PropertyConformance::{Optional, RequiredRead},
PropertyMetadata,
PropertyWriteCapability::{Always, ReadOnly},
};
use bacnet_types::enums::{IPMode, PropertyIdentifier as P};
use std::borrow::Cow;
const COMMON: &[PropertyMetadata] = &[
PropertyMetadata::new(P::OBJECT_IDENTIFIER, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::OBJECT_NAME, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::DESCRIPTION, Optional, None, Always),
PropertyMetadata::new(P::OBJECT_TYPE, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::STATUS_FLAGS, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::OUT_OF_SERVICE, RequiredRead, None, Always),
PropertyMetadata::new(P::RELIABILITY, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::NETWORK_TYPE, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::PROTOCOL_LEVEL, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::NETWORK_NUMBER, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::NETWORK_NUMBER_QUALITY, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::MAC_ADDRESS, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::APDU_LENGTH, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::LINK_SPEED, Optional, None, ReadOnly),
PropertyMetadata::new(P::CHANGES_PENDING, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::PROPERTY_LIST, RequiredRead, None, ReadOnly),
];
const BIP: &[PropertyMetadata] = &[
PropertyMetadata::new(P::BACNET_IP_MODE, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::IP_ADDRESS, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::IP_DEFAULT_GATEWAY, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::IP_SUBNET_MASK, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::BACNET_IP_UDP_PORT, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::IP_DNS_SERVER, RequiredRead, None, ReadOnly),
];
const BIP6: &[PropertyMetadata] = &[
PropertyMetadata::new(P::BACNET_IPV6_MODE, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::IPV6_ADDRESS, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::IPV6_PREFIX_LENGTH, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::BACNET_IPV6_UDP_PORT, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::IPV6_DEFAULT_GATEWAY, RequiredRead, None, ReadOnly),
PropertyMetadata::new(
P::BACNET_IPV6_MULTICAST_ADDRESS,
RequiredRead,
None,
ReadOnly,
),
PropertyMetadata::new(P::IPV6_DNS_SERVER, RequiredRead, None, ReadOnly),
];
const BBMD: &[PropertyMetadata] = &[
PropertyMetadata::new(
P::BBMD_BROADCAST_DISTRIBUTION_TABLE,
RequiredRead,
None,
ReadOnly,
),
PropertyMetadata::new(
P::BBMD_ACCEPT_FD_REGISTRATIONS,
RequiredRead,
None,
ReadOnly,
),
PropertyMetadata::new(P::BBMD_FOREIGN_DEVICE_TABLE, RequiredRead, None, ReadOnly),
];
const NAT: &[PropertyMetadata] = &[
PropertyMetadata::new(P::BACNET_IP_NAT_TRAVERSAL, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::BACNET_IP_GLOBAL_ADDRESS, Optional, None, ReadOnly),
];
const MULTICAST: &[PropertyMetadata] = &[PropertyMetadata::new(
P::BACNET_IP_MULTICAST_ADDRESS,
RequiredRead,
None,
ReadOnly,
)];
const FOREIGN: &[PropertyMetadata] = &[
PropertyMetadata::new(P::FD_BBMD_ADDRESS, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::FD_SUBSCRIPTION_LIFETIME, RequiredRead, None, ReadOnly),
];
pub(super) fn for_object(object: &NetworkPortObject) -> Cow<'_, [PropertyMetadata]> {
if let Some(config) = &object.ip {
let profile = match config {
IpConfig::V4(_) => BIP,
IpConfig::V6(_) => BIP6,
};
let mode: &[PropertyMetadata] = match object.mode.ip_mode() {
IPMode::BBMD => BBMD,
IPMode::FOREIGN => FOREIGN,
_ => &[],
};
let nat: &[PropertyMetadata] = if object.serves_nat() { NAT } else { &[] };
let multicast: &[PropertyMetadata] = if object.serves_multicast() {
MULTICAST
} else {
&[]
};
Cow::Owned(
COMMON
.iter()
.chain(profile)
.chain(multicast)
.chain(nat)
.chain(mode)
.copied()
.map(|mut row| {
if row.property_identifier == P::OUT_OF_SERVICE && object.is_bound() {
row.write_capability = ReadOnly;
}
if row.property_identifier == P::BACNET_IP_GLOBAL_ADDRESS
&& object.mode.nat_on()
{
row.conformance = RequiredRead;
}
if object.activates_changes()
&& super::pending::writable_pending_row(row.property_identifier)
{
row.write_capability = Always;
}
if row.property_identifier == P::BACNET_IP_MULTICAST_ADDRESS
&& object.activates_multicast()
{
row.write_capability = Always;
}
row
})
.collect(),
)
} else {
Cow::Borrowed(COMMON)
}
}