use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimConfig {
pub device: DeviceConfig,
#[serde(default)]
pub registers: RegisterConfig,
#[serde(default)]
pub faults: Vec<FaultConfig>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeviceConfig {
#[serde(default = "default_unit_id")]
pub unit_id: u8,
#[serde(default = "default_vendor")]
pub vendor_name: String,
#[serde(default = "default_product")]
pub product_code: String,
#[serde(default = "default_revision")]
pub revision: String,
#[serde(default = "default_listen")]
pub listen_addr: String,
}
fn default_unit_id() -> u8 {
1
}
fn default_vendor() -> String {
String::from("rusty-modbus-sim")
}
fn default_product() -> String {
String::from("SIM")
}
fn default_revision() -> String {
String::from("0.1.0")
}
fn default_listen() -> String {
String::from("127.0.0.1:0")
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct RegisterConfig {
#[serde(default)]
pub holding: Vec<RegisterBlock>,
#[serde(default)]
pub input: Vec<RegisterBlock>,
#[serde(default)]
pub coils: Vec<CoilBlock>,
#[serde(default)]
pub discrete_inputs: Vec<CoilBlock>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RegisterBlock {
pub address: u16,
pub count: u16,
#[serde(default)]
pub initial: Vec<u16>,
#[serde(default)]
pub mode: UpdateMode,
#[serde(default)]
pub min: u16,
#[serde(default = "default_max_u16")]
pub max: u16,
}
fn default_max_u16() -> u16 {
1000
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CoilBlock {
pub address: u16,
pub count: u16,
#[serde(default)]
pub initial: Vec<bool>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum UpdateMode {
#[default]
Static,
Random,
Increment,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FaultConfig {
#[serde(rename = "type")]
pub fault_type: FaultType,
#[serde(default)]
pub trigger: FaultTrigger,
#[serde(default)]
pub exception: Option<String>,
#[serde(default)]
pub delay_ms: Option<u64>,
#[serde(default)]
pub probability: Option<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum FaultType {
Exception,
Delay,
Timeout,
Corrupt,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct FaultTrigger {
pub function: Option<String>,
pub address: Option<u16>,
pub unit_id: Option<u8>,
}