use crate::network_port::{BipPortConfig, NetworkPortObject};
use bacnet_types::{enums::NetworkType, error::Error, MacAddr};
use std::net::Ipv4Addr;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct NetworkPortEntry {
pub instance: u32,
pub network_type: u32,
pub network_number: u32,
pub mac: MacAddr,
pub ip: [u8; 4],
pub udp_port: u16,
}
impl NetworkPortEntry {
pub fn bip(instance: u32, network_number: u32, ip: Ipv4Addr, udp_port: u16) -> Self {
let o = ip.octets();
let mut mac = MacAddr::new();
mac.extend_from_slice(&o);
mac.extend_from_slice(&udp_port.to_be_bytes());
Self {
instance,
network_type: NetworkType::IPV4.to_raw(),
network_number,
mac,
ip: o,
udp_port,
}
}
pub(super) fn build_object(&self) -> Result<NetworkPortObject, Error> {
let network_number = u16::try_from(self.network_number)
.map_err(|_| Error::Encoding("network number must be 0..65534".into()))?;
let name = format!("port-{}", self.instance);
let apdu_length = 1476;
if self.network_type == NetworkType::IPV4.to_raw() {
let [a, b, c, d] = self.ip;
let [hi, lo] = self.udp_port.to_be_bytes();
if self.mac.as_slice() != [a, b, c, d, hi, lo] {
return Err(Error::Encoding(
"B/IP MAC must match configured IPv4 address and UDP port".into(),
));
}
NetworkPortObject::new_bip(
self.instance,
name,
BipPortConfig {
network_number,
apdu_length,
ip_address: self.ip,
udp_port: self.udp_port,
..Default::default()
},
)
} else {
NetworkPortObject::new_non_bip(
self.instance,
name,
NetworkType::from_raw(self.network_type),
network_number,
self.mac.clone(),
apdu_length,
)
}
}
pub fn sc(instance: u32, network_number: u32, vmac: [u8; 6]) -> Self {
Self {
instance,
network_type: NetworkType::VIRTUAL.to_raw(),
network_number,
mac: MacAddr::from_slice(&vmac),
ip: [0; 4],
udp_port: 0,
}
}
}