use crate::app::{BufferSize, Timeout};
use crate::decode::DecodeLevel;
use crate::link::EndpointAddress;
use crate::outstation::database::{ClassZeroConfig, EventBufferConfig};
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(
feature = "serialization",
derive(serde::Serialize, serde::Deserialize)
)]
pub enum Feature {
Enabled,
Disabled,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(
feature = "serialization",
derive(serde::Serialize, serde::Deserialize)
)]
#[cfg_attr(not(feature = "ffi"), non_exhaustive)]
pub struct Features {
pub self_address: Feature,
pub broadcast: Feature,
pub unsolicited: Feature,
pub respond_to_any_master: Feature,
}
impl Default for Features {
fn default() -> Self {
Self {
self_address: Feature::Disabled,
broadcast: Feature::Enabled,
unsolicited: Feature::Enabled,
respond_to_any_master: Feature::Disabled,
}
}
}
#[derive(Copy, Clone, Debug)]
#[cfg_attr(
feature = "serialization",
derive(serde::Serialize, serde::Deserialize)
)]
pub struct OutstationConfig {
pub outstation_address: EndpointAddress,
pub master_address: EndpointAddress,
pub event_buffer_config: EventBufferConfig,
#[cfg_attr(feature = "serialization", serde(default))]
pub solicited_buffer_size: BufferSize,
#[cfg_attr(feature = "serialization", serde(default))]
pub unsolicited_buffer_size: BufferSize,
#[cfg_attr(feature = "serialization", serde(default))]
pub rx_buffer_size: BufferSize,
#[cfg_attr(feature = "serialization", serde(default))]
pub decode_level: DecodeLevel,
#[cfg_attr(feature = "serialization", serde(default))]
pub confirm_timeout: Timeout,
#[cfg_attr(feature = "serialization", serde(default))]
pub select_timeout: Timeout,
#[cfg_attr(feature = "serialization", serde(default))]
pub features: Features,
#[cfg_attr(feature = "serialization", serde(default))]
pub max_unsolicited_retries: Option<usize>,
#[cfg_attr(
feature = "serialization",
serde(default = "OutstationConfig::default_unsolicited_retry_delay")
)]
pub unsolicited_retry_delay: std::time::Duration,
#[cfg_attr(
feature = "serialization",
serde(default = "OutstationConfig::default_keep_alive_timeout")
)]
pub keep_alive_timeout: Option<std::time::Duration>,
#[cfg_attr(feature = "serialization", serde(default))]
pub max_read_request_headers: Option<u16>,
#[cfg_attr(feature = "serialization", serde(default))]
pub max_controls_per_request: Option<u16>,
#[cfg_attr(feature = "serialization", serde(default))]
pub class_zero: ClassZeroConfig,
}
impl Feature {
pub(crate) fn is_enabled(&self) -> bool {
*self == Feature::Enabled
}
pub(crate) fn is_disabled(&self) -> bool {
*self == Feature::Disabled
}
}
impl OutstationConfig {
const fn default_keep_alive_timeout() -> Option<core::time::Duration> {
Some(core::time::Duration::from_secs(60))
}
const fn default_unsolicited_retry_delay() -> core::time::Duration {
std::time::Duration::from_secs(5)
}
pub const DEFAULT_MAX_READ_REQUEST_HEADERS: u16 = 64;
pub const DEFAULT_CONFIRM_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5);
pub const DEFAULT_SELECT_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5);
pub const DEFAULT_UNSOLICITED_RETRY_DELAY: std::time::Duration =
Self::default_unsolicited_retry_delay();
pub fn new(
outstation_address: EndpointAddress,
master_address: EndpointAddress,
event_buffer_config: EventBufferConfig,
) -> Self {
Self {
outstation_address,
master_address,
event_buffer_config,
solicited_buffer_size: BufferSize::default(),
unsolicited_buffer_size: BufferSize::default(),
rx_buffer_size: BufferSize::default(),
decode_level: DecodeLevel::nothing(),
confirm_timeout: Timeout::default(),
select_timeout: Timeout::default(),
features: Features::default(),
max_unsolicited_retries: None,
unsolicited_retry_delay: Self::DEFAULT_UNSOLICITED_RETRY_DELAY,
keep_alive_timeout: Self::default_keep_alive_timeout(),
max_read_request_headers: None,
max_controls_per_request: None,
class_zero: ClassZeroConfig::default(),
}
}
}
#[cfg(test)]
#[cfg(feature = "serialization")]
mod test {
#[test]
fn deserialization_allows_defaults() {
assert!(serde_json::from_str::<super::OutstationConfig>("{}").is_err());
let data = r#"{
"outstation_address": 64,
"master_address": 99,
"event_buffer_config": {
"max_binary": 7
}
}"#;
let config = serde_json::from_str::<super::OutstationConfig>(data).unwrap();
assert_eq!(config.outstation_address.raw_value(), 64);
assert_eq!(config.master_address.raw_value(), 99);
assert_eq!(config.event_buffer_config.max_binary, 7);
assert_eq!(config.event_buffer_config.max_analog, 0);
assert_eq!(config.rx_buffer_size.value(), 2048);
}
}