use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub struct AppConfig {
#[serde(default)]
pub general: GeneralConfig,
#[serde(default)]
pub pcap: Option<PcapConfig>,
#[serde(default)]
pub csv: Option<CsvConfig>,
#[serde(default)]
pub upstream: Vec<UpstreamConfig>,
#[serde(default)]
pub downstream: Vec<DownstreamConfig>,
#[serde(default)]
pub route: Vec<RouteConfig>,
#[serde(default)]
pub rewrite: Option<RewriteConfig>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct GeneralConfig {
#[serde(default = "default_log_level")]
pub log_level: String,
#[serde(default = "default_true")]
pub tui: bool,
}
impl Default for GeneralConfig {
fn default() -> Self {
Self {
log_level: default_log_level(),
tui: true,
}
}
}
fn default_log_level() -> String {
"info".to_string()
}
fn default_true() -> bool {
true
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct PcapConfig {
#[serde(default)]
pub enabled: bool,
pub path: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CsvConfig {
#[serde(default)]
pub enabled: bool,
pub path: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(tag = "type", rename_all = "lowercase")]
pub enum UpstreamConfig {
Tcp(TcpUpstreamConfig),
Websocket(WsUpstreamConfig),
Serial(SerialUpstreamConfig),
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct TcpUpstreamConfig {
pub bind: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct WsUpstreamConfig {
pub bind: String,
#[serde(default)]
pub idle_timeout_secs: Option<u64>,
#[serde(default)]
pub max_sessions: usize,
#[serde(default)]
pub require_subprotocol: bool,
#[serde(default)]
pub allowed_origins: Vec<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct SerialUpstreamConfig {
pub port: String,
#[serde(default = "default_mode")]
pub mode: String,
#[serde(default = "default_baud")]
pub baud_rate: u32,
#[serde(default = "default_data_bits")]
pub data_bits: u8,
#[serde(default = "default_stop_bits")]
pub stop_bits: u8,
#[serde(default = "default_parity")]
pub parity: String,
#[serde(default = "default_timeout_ms")]
pub response_timeout_ms: u64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(tag = "type", rename_all = "lowercase")]
pub enum DownstreamConfig {
Tcp(TcpDownstreamConfig),
Serial(SerialDownstreamConfig),
}
impl DownstreamConfig {
pub fn name(&self) -> &str {
match self {
DownstreamConfig::Tcp(c) => &c.name,
DownstreamConfig::Serial(c) => &c.name,
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct TcpDownstreamConfig {
pub name: String,
pub address: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct SerialDownstreamConfig {
pub name: String,
pub port: String,
#[serde(default = "default_mode")]
pub mode: String,
#[serde(default = "default_baud")]
pub baud_rate: u32,
#[serde(default = "default_data_bits")]
pub data_bits: u8,
#[serde(default = "default_stop_bits")]
pub stop_bits: u8,
#[serde(default = "default_parity")]
pub parity: String,
#[serde(default = "default_timeout_ms")]
pub response_timeout_ms: u64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(tag = "type", rename_all = "lowercase")]
pub enum RouteConfig {
Unit(UnitRouteConfig),
Range(RangeRouteConfig),
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct UnitRouteConfig {
pub unit_id: u8,
pub downstream: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct RangeRouteConfig {
pub min_unit: u8,
pub max_unit: u8,
pub downstream: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct RewriteConfig {
pub offset: i16,
}
fn default_mode() -> String {
"rtu".to_string()
}
fn default_baud() -> u32 {
19200
}
fn default_data_bits() -> u8 {
8
}
fn default_stop_bits() -> u8 {
1
}
fn default_parity() -> String {
"none".to_string()
}
fn default_timeout_ms() -> u64 {
1000
}