ccs: modbus tcp
This commit is contained in:
parent
813f26500c
commit
23fe7acbb0
5 changed files with 145 additions and 26 deletions
|
@ -121,9 +121,13 @@ pub async fn write_to_config<'a>() -> ConfigHandle<'a> {
|
|||
#[serde(tag = "version")]
|
||||
pub enum ConfigStorage {
|
||||
#[serde(rename = "1")]
|
||||
V1(Config),
|
||||
V1(outdated::ConfigV1),
|
||||
#[serde(rename = "2")]
|
||||
V2(Config),
|
||||
}
|
||||
|
||||
mod outdated;
|
||||
|
||||
impl Default for ConfigStorage {
|
||||
fn default() -> Self {
|
||||
Self::from_latest(Default::default())
|
||||
|
@ -131,8 +135,15 @@ impl Default for ConfigStorage {
|
|||
}
|
||||
|
||||
impl ConfigStorage {
|
||||
const fn from_latest(config: Config) -> Self {
|
||||
Self::V1(config)
|
||||
pub const fn from_latest(config: Config) -> Self {
|
||||
Self::V2(config)
|
||||
}
|
||||
|
||||
pub fn into_latest(self) -> Config {
|
||||
match self {
|
||||
ConfigStorage::V1(v1) => v1.into(),
|
||||
ConfigStorage::V2(config) => config,
|
||||
}
|
||||
}
|
||||
|
||||
fn load(path: impl AsRef<std::path::Path>) -> eyre::Result<Self> {
|
||||
|
@ -149,12 +160,6 @@ impl ConfigStorage {
|
|||
fn save(&self) -> eyre::Result<()> {
|
||||
self.save_to(CONFIG_PATH.get().unwrap())
|
||||
}
|
||||
|
||||
fn into_latest(self) -> Config {
|
||||
match self {
|
||||
ConfigStorage::V1(config) => config,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
|
||||
|
@ -181,12 +186,11 @@ impl Config {
|
|||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
pub struct ChargeControllerConfig {
|
||||
pub name: String,
|
||||
pub serial_port: String,
|
||||
pub baud_rate: u32,
|
||||
pub watch_interval_seconds: u64,
|
||||
pub variant: ChargeControllerVariant,
|
||||
#[serde(default)]
|
||||
pub follow_primary: bool,
|
||||
pub transport: Transport,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
|
@ -194,3 +198,10 @@ pub enum ChargeControllerVariant {
|
|||
Tristar,
|
||||
Pl { timeout_milliseconds: u64 },
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Transport {
|
||||
Serial { port: String, baud_rate: u32 },
|
||||
Tcp { ip: std::net::IpAddr, port: u16 },
|
||||
}
|
||||
|
|
72
charge-controller-supervisor/src/config/outdated.rs
Normal file
72
charge-controller-supervisor/src/config/outdated.rs
Normal file
|
@ -0,0 +1,72 @@
|
|||
pub use v1::ConfigV1;
|
||||
|
||||
mod v1 {
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
|
||||
#[serde(default)]
|
||||
pub struct ConfigV1 {
|
||||
primary_charge_controller: String,
|
||||
enable_secondary_control: bool,
|
||||
charge_controllers: Vec<ChargeControllerConfigV1>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
struct ChargeControllerConfigV1 {
|
||||
name: String,
|
||||
serial_port: String,
|
||||
baud_rate: u32,
|
||||
watch_interval_seconds: u64,
|
||||
variant: ChargeControllerVariantV1,
|
||||
#[serde(default)]
|
||||
follow_primary: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
enum ChargeControllerVariantV1 {
|
||||
Tristar,
|
||||
Pl { timeout_milliseconds: u64 },
|
||||
}
|
||||
|
||||
impl From<ChargeControllerConfigV1> for crate::config::ChargeControllerConfig {
|
||||
fn from(value: ChargeControllerConfigV1) -> Self {
|
||||
Self {
|
||||
name: value.name,
|
||||
transport: crate::config::Transport::Serial {
|
||||
port: value.serial_port,
|
||||
baud_rate: value.baud_rate,
|
||||
},
|
||||
watch_interval_seconds: value.watch_interval_seconds,
|
||||
variant: value.variant.into(),
|
||||
follow_primary: value.follow_primary,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ChargeControllerVariantV1> for crate::config::ChargeControllerVariant {
|
||||
fn from(value: ChargeControllerVariantV1) -> Self {
|
||||
match value {
|
||||
ChargeControllerVariantV1::Tristar => Self::Tristar,
|
||||
ChargeControllerVariantV1::Pl {
|
||||
timeout_milliseconds,
|
||||
} => Self::Pl {
|
||||
timeout_milliseconds,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ConfigV1> for crate::config::Config {
|
||||
fn from(value: ConfigV1) -> Self {
|
||||
Self {
|
||||
primary_charge_controller: value.primary_charge_controller,
|
||||
enable_secondary_control: value.enable_secondary_control,
|
||||
charge_controllers: value
|
||||
.charge_controllers
|
||||
.into_iter()
|
||||
.map(Into::into)
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,17 +28,18 @@ impl Controller {
|
|||
)> {
|
||||
let inner = match config.variant {
|
||||
crate::config::ChargeControllerVariant::Tristar => ControllerInner::Tristar(
|
||||
crate::tristar::Tristar::new(&config.serial_port, &config.name, config.baud_rate)
|
||||
.await?,
|
||||
crate::tristar::Tristar::new(&config.name, &config.transport).await?,
|
||||
),
|
||||
crate::config::ChargeControllerVariant::Pl {
|
||||
timeout_milliseconds,
|
||||
} => ControllerInner::Pl(crate::pl::Pli::new(
|
||||
&config.serial_port,
|
||||
&config.name,
|
||||
config.baud_rate,
|
||||
timeout_milliseconds,
|
||||
)?),
|
||||
} => match &config.transport {
|
||||
crate::config::Transport::Serial { port, baud_rate } => ControllerInner::Pl(
|
||||
crate::pl::Pli::new(port, &config.name, *baud_rate, timeout_milliseconds)?,
|
||||
),
|
||||
crate::config::Transport::Tcp { ip: _, port: _ } => {
|
||||
return Err(eyre::eyre!("pl doesn't support tcp"))
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let data = CommonData::default();
|
||||
|
|
|
@ -59,7 +59,32 @@ async fn run() -> eyre::Result<()> {
|
|||
match args.command {
|
||||
Commands::Watch => watch(args).await,
|
||||
Commands::GenerateConfig => {
|
||||
let config = config::ConfigStorage::default();
|
||||
let mut config = config::Config::default();
|
||||
config
|
||||
.charge_controllers
|
||||
.push(config::ChargeControllerConfig {
|
||||
name: String::from("tcp"),
|
||||
transport: config::Transport::Tcp {
|
||||
ip: std::net::IpAddr::V4(std::net::Ipv4Addr::new(192, 168, 1, 102)),
|
||||
port: 420,
|
||||
},
|
||||
watch_interval_seconds: 0,
|
||||
variant: config::ChargeControllerVariant::Tristar,
|
||||
follow_primary: false,
|
||||
});
|
||||
config
|
||||
.charge_controllers
|
||||
.push(config::ChargeControllerConfig {
|
||||
name: String::from("serial"),
|
||||
transport: config::Transport::Serial {
|
||||
port: "/dev/someport".to_string(),
|
||||
baud_rate: 69,
|
||||
},
|
||||
watch_interval_seconds: 0,
|
||||
variant: config::ChargeControllerVariant::Tristar,
|
||||
follow_primary: false,
|
||||
});
|
||||
let config = config::ConfigStorage::from_latest(config);
|
||||
let json = serde_json::to_string_pretty(&config)?;
|
||||
println!("{json}");
|
||||
Ok(())
|
||||
|
|
|
@ -280,13 +280,23 @@ impl ChargeStateGauges {
|
|||
}
|
||||
|
||||
impl Tristar {
|
||||
pub async fn new(serial_port: &str, friendly_name: &str, baud_rate: u32) -> eyre::Result<Self> {
|
||||
let modbus_serial = tokio_serial::SerialStream::open(
|
||||
&tokio_serial::new(serial_port, baud_rate).timeout(std::time::Duration::from_secs(3)),
|
||||
)?;
|
||||
|
||||
pub async fn new(
|
||||
friendly_name: &str,
|
||||
transport: &crate::config::Transport,
|
||||
) -> eyre::Result<Self> {
|
||||
let slave = tokio_modbus::Slave(DEVICE_ID);
|
||||
let modbus = tokio_modbus::client::rtu::attach_slave(modbus_serial, slave);
|
||||
|
||||
let modbus = match transport {
|
||||
crate::config::Transport::Serial { port, baud_rate } => {
|
||||
let modbus_serial =
|
||||
tokio_serial::SerialStream::open(&tokio_serial::new(port, *baud_rate))?;
|
||||
tokio_modbus::client::rtu::attach_slave(modbus_serial, slave)
|
||||
}
|
||||
crate::config::Transport::Tcp { ip, port } => {
|
||||
tokio_modbus::client::tcp::connect((*ip, *port).into()).await?
|
||||
}
|
||||
};
|
||||
|
||||
let mut modbus = ModbusTimeout(modbus);
|
||||
|
||||
let scaling = {
|
||||
|
|
Loading…
Add table
Reference in a new issue