ccs: tristar: expose settings
This commit is contained in:
parent
ed82c3444e
commit
a908490bb0
5 changed files with 422 additions and 1 deletions
|
@ -30,5 +30,6 @@ default-trait-access = { level = "allow", priority = 1 }
|
||||||
missing-errors-doc = { level = "allow", priority = 1 }
|
missing-errors-doc = { level = "allow", priority = 1 }
|
||||||
missing-panics-doc = { level = "allow", priority = 1 }
|
missing-panics-doc = { level = "allow", priority = 1 }
|
||||||
module-name-repetitions = { level = "allow", priority = 1 }
|
module-name-repetitions = { level = "allow", priority = 1 }
|
||||||
|
similar-names = { level = "allow", priority = 1 }
|
||||||
struct-excessive-bools = { level = "allow", priority = 1 }
|
struct-excessive-bools = { level = "allow", priority = 1 }
|
||||||
too-many-lines = { level = "allow", priority = 1 }
|
too-many-lines = { level = "allow", priority = 1 }
|
||||||
|
|
|
@ -43,6 +43,12 @@ impl ControllerState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, Clone)]
|
||||||
|
#[serde(tag = "model")]
|
||||||
|
pub enum ControllerSettings {
|
||||||
|
Tristar(tristar::TristarSettings),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum VoltageCommand {
|
pub enum VoltageCommand {
|
||||||
Set(f64),
|
Set(f64),
|
||||||
|
@ -55,7 +61,7 @@ impl Controller {
|
||||||
Self,
|
Self,
|
||||||
Option<tokio::sync::mpsc::UnboundedSender<VoltageCommand>>,
|
Option<tokio::sync::mpsc::UnboundedSender<VoltageCommand>>,
|
||||||
)> {
|
)> {
|
||||||
let inner = match config.variant {
|
let mut inner = match config.variant {
|
||||||
crate::config::ChargeControllerVariant::Tristar => ControllerInner::Tristar(
|
crate::config::ChargeControllerVariant::Tristar => ControllerInner::Tristar(
|
||||||
tristar::Tristar::new(&config.name, &config.transport).await?,
|
tristar::Tristar::new(&config.name, &config.transport).await?,
|
||||||
),
|
),
|
||||||
|
@ -73,6 +79,15 @@ impl Controller {
|
||||||
|
|
||||||
let data = std::sync::Arc::new(ControllerData::new());
|
let data = std::sync::Arc::new(ControllerData::new());
|
||||||
|
|
||||||
|
if let ControllerInner::Tristar(t) = &mut inner {
|
||||||
|
match t.read_settings().await {
|
||||||
|
Ok(v) => {
|
||||||
|
*data.write_settings().await = Some(ControllerSettings::Tristar(v));
|
||||||
|
}
|
||||||
|
Err(e) => log::error!("couldn't read config from tristar {}: {e:?}", config.name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let (voltage_tx, voltage_rx) = if config.follow_primary {
|
let (voltage_tx, voltage_rx) = if config.follow_primary {
|
||||||
let (a, b) = tokio::sync::mpsc::unbounded_channel();
|
let (a, b) = tokio::sync::mpsc::unbounded_channel();
|
||||||
(Some(a), Some(b))
|
(Some(a), Some(b))
|
||||||
|
|
|
@ -80,6 +80,286 @@ impl ModbusTimeout {
|
||||||
Ok(v)
|
Ok(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
|
pub struct TristarSettings {
|
||||||
|
network: NetworkSettings,
|
||||||
|
charge: ChargeSettings,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
|
pub struct NetworkSettings {
|
||||||
|
http_port: u16,
|
||||||
|
modbus_port: u16,
|
||||||
|
ip_bridging_enabled: bool,
|
||||||
|
snmp_trap_port: u16,
|
||||||
|
ethernet_power_saving: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
const NETWORK_DATA_ADDR_START: u16 = 0x151b;
|
||||||
|
const NETWORK_DATA_ADDR_END: u16 = 0x1521;
|
||||||
|
const NETWORK_DATA_LENGTH: u16 = NETWORK_DATA_ADDR_END - NETWORK_DATA_ADDR_START;
|
||||||
|
|
||||||
|
impl NetworkSettings {
|
||||||
|
fn from_buf(buf: &[u16]) -> eyre::Result<Self> {
|
||||||
|
fn get(buf: &[u16], addr: TristarEepromAddress) -> eyre::Result<u16> {
|
||||||
|
let addr = (addr as u16)
|
||||||
|
.checked_sub(NETWORK_DATA_ADDR_START)
|
||||||
|
.ok_or_else(|| eyre::eyre!("wrong address range!"))?;
|
||||||
|
|
||||||
|
let word = buf
|
||||||
|
.get::<usize>(addr.into())
|
||||||
|
.ok_or_else(|| eyre::eyre!("address out of bounds!"))?;
|
||||||
|
Ok(*word)
|
||||||
|
}
|
||||||
|
|
||||||
|
let http_port = get(buf, TristarEepromAddress::HTTPPort)?;
|
||||||
|
let modbus_port = get(buf, TristarEepromAddress::MBIPPort)?;
|
||||||
|
let ip_bridging_enabled = get(buf, TristarEepromAddress::NetRules)? != 0;
|
||||||
|
let snmp_trap_port = get(buf, TristarEepromAddress::SNMPTrapRecPort)?;
|
||||||
|
let ethernet_power_saving = get(buf, TristarEepromAddress::EthernetPowerSaveMode)? == 1;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
http_port,
|
||||||
|
modbus_port,
|
||||||
|
ip_bridging_enabled,
|
||||||
|
snmp_trap_port,
|
||||||
|
ethernet_power_saving,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
|
pub struct ChargeSettings {
|
||||||
|
absorption_voltage: f64,
|
||||||
|
float_voltage: f64,
|
||||||
|
absorption_time_seconds: u16,
|
||||||
|
absorption_extension_time_seconds: u16,
|
||||||
|
absorption_extension_voltage: f64,
|
||||||
|
float_cancel_voltage: f64,
|
||||||
|
float_exit_timer_seconds: u16,
|
||||||
|
equalize_voltage: f64,
|
||||||
|
equalize_interval_days: u16,
|
||||||
|
equalize_time_limit_above_vreg: u16,
|
||||||
|
equalize_time_limit_at_veq: u16,
|
||||||
|
battery_service_days: u16,
|
||||||
|
temperature_compensation_raw: u16,
|
||||||
|
high_voltage_disconnect: f64,
|
||||||
|
high_voltage_reconnect: f64,
|
||||||
|
battery_charge_reference_limit: f64,
|
||||||
|
max_temp_comp_raw: u16,
|
||||||
|
min_temp_comp_raw: u16,
|
||||||
|
modbus_slave_address: u16,
|
||||||
|
meterbus_address: u16,
|
||||||
|
battery_current_limit: f64,
|
||||||
|
array_target_voltage: f64,
|
||||||
|
array_target_voltage_percentage_raw: u16,
|
||||||
|
led_thresholds: LedThresholds,
|
||||||
|
read_only: ReadOnly,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
|
pub struct LedThresholds {
|
||||||
|
green_to_greenyellow: f64,
|
||||||
|
greenyellow_to_yellow: f64,
|
||||||
|
yellow_to_yellowred: f64,
|
||||||
|
yellowred_to_red: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
|
pub struct ReadOnly {
|
||||||
|
hourmeter: u32,
|
||||||
|
charge_ah_resetable: f64,
|
||||||
|
charge_ah_total: f64,
|
||||||
|
charge_kwh_resetable: u16,
|
||||||
|
charge_kwh_total: u16,
|
||||||
|
vb_min: f64,
|
||||||
|
vb_max: f64,
|
||||||
|
va_max: f64,
|
||||||
|
days_since_last_equalize: u16,
|
||||||
|
battery_service_timer_days: u16,
|
||||||
|
serial: u64,
|
||||||
|
model: Model,
|
||||||
|
hardware_version: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
|
pub enum Model {
|
||||||
|
Tristar45A,
|
||||||
|
Tristar60A,
|
||||||
|
}
|
||||||
|
|
||||||
|
const CHARGE_DATA_ADDR_START: u16 = 0xE000;
|
||||||
|
|
||||||
|
impl ChargeSettings {
|
||||||
|
fn from_buf(buf: &[u16], scaling: &Scaling) -> eyre::Result<Self> {
|
||||||
|
fn get(buf: &[u16], address: TristarEepromAddress) -> eyre::Result<u16> {
|
||||||
|
let addr = (address as u16)
|
||||||
|
.checked_sub(CHARGE_DATA_ADDR_START)
|
||||||
|
.ok_or_else(|| eyre::eyre!("wrong address range!"))?;
|
||||||
|
|
||||||
|
let word = buf
|
||||||
|
.get::<usize>(addr.into())
|
||||||
|
.ok_or_else(|| eyre::eyre!("address {address:?} out of bounds at {addr:#X?}!"))?;
|
||||||
|
Ok(*word)
|
||||||
|
}
|
||||||
|
|
||||||
|
let absorption_voltage = scaling.get_voltage(get(buf, TristarEepromAddress::EvAbsorp)?);
|
||||||
|
let float_voltage = scaling.get_voltage(get(buf, TristarEepromAddress::EvFloat)?);
|
||||||
|
|
||||||
|
let absorption_time_seconds = get(buf, TristarEepromAddress::EtAbsorp)?;
|
||||||
|
let absorption_extension_time_seconds = get(buf, TristarEepromAddress::EtAbsorp)?;
|
||||||
|
|
||||||
|
let absorption_extension_voltage =
|
||||||
|
scaling.get_voltage(get(buf, TristarEepromAddress::EvAbsorpExt)?);
|
||||||
|
let float_cancel_voltage =
|
||||||
|
scaling.get_voltage(get(buf, TristarEepromAddress::EvFloatCancel)?);
|
||||||
|
|
||||||
|
let float_exit_timer_seconds = get(buf, TristarEepromAddress::EtFloatExitCum)?;
|
||||||
|
|
||||||
|
let equalize_voltage = scaling.get_voltage(get(buf, TristarEepromAddress::EvEq)?);
|
||||||
|
let equalize_interval_days = get(buf, TristarEepromAddress::EtEqcalendar)?;
|
||||||
|
let equalize_time_limit_above_vreg = get(buf, TristarEepromAddress::EtEqAbove)?;
|
||||||
|
let equalize_time_limit_at_veq = get(buf, TristarEepromAddress::EtEqReg)?;
|
||||||
|
|
||||||
|
let battery_service_days = get(buf, TristarEepromAddress::EtBattService)?;
|
||||||
|
|
||||||
|
let temperature_compensation_raw = get(buf, TristarEepromAddress::EvTempcomp)?;
|
||||||
|
|
||||||
|
let high_voltage_disconnect = scaling.get_voltage(get(buf, TristarEepromAddress::EvHvd)?);
|
||||||
|
let high_voltage_reconnect = scaling.get_voltage(get(buf, TristarEepromAddress::EvHvr)?);
|
||||||
|
|
||||||
|
let battery_charge_reference_limit =
|
||||||
|
scaling.get_voltage(get(buf, TristarEepromAddress::EvbRefLim)?);
|
||||||
|
|
||||||
|
let max_temp_comp_raw = get(buf, TristarEepromAddress::EtbMax)?;
|
||||||
|
let min_temp_comp_raw = get(buf, TristarEepromAddress::EtbMin)?;
|
||||||
|
|
||||||
|
let led_thresholds = {
|
||||||
|
let green_to_greenyellow =
|
||||||
|
scaling.get_voltage(get(buf, TristarEepromAddress::EvSocGGy)?);
|
||||||
|
let greenyellow_to_yellow =
|
||||||
|
scaling.get_voltage(get(buf, TristarEepromAddress::EvSocGyY)?);
|
||||||
|
let yellow_to_yellowred =
|
||||||
|
scaling.get_voltage(get(buf, TristarEepromAddress::EvSocYYr)?);
|
||||||
|
let yellowred_to_red = scaling.get_voltage(get(buf, TristarEepromAddress::EvSocYrR)?);
|
||||||
|
|
||||||
|
LedThresholds {
|
||||||
|
green_to_greenyellow,
|
||||||
|
greenyellow_to_yellow,
|
||||||
|
yellow_to_yellowred,
|
||||||
|
yellowred_to_red,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let modbus_slave_address = get(buf, TristarEepromAddress::EmodbusId)?;
|
||||||
|
let meterbus_address = get(buf, TristarEepromAddress::EmeterbusId)?;
|
||||||
|
|
||||||
|
let battery_current_limit = scaling.get_current(get(buf, TristarEepromAddress::EibLim)?);
|
||||||
|
|
||||||
|
let array_target_voltage =
|
||||||
|
scaling.get_voltage(get(buf, TristarEepromAddress::EvaRefFixedInit)?);
|
||||||
|
let array_target_voltage_percentage_raw =
|
||||||
|
get(buf, TristarEepromAddress::EvaRefFixedPctInit)?;
|
||||||
|
|
||||||
|
let read_only = {
|
||||||
|
let hourmeter = {
|
||||||
|
let hourmeter_lo = get(buf, TristarEepromAddress::EhourmeterLo)?;
|
||||||
|
let hourmeter_hi = get(buf, TristarEepromAddress::EhourmeterHi)?;
|
||||||
|
u32::from(hourmeter_lo) | (u32::from(hourmeter_hi) << 16)
|
||||||
|
};
|
||||||
|
|
||||||
|
let charge_ah_resetable = {
|
||||||
|
let charge_ah_resetable_lo = get(buf, TristarEepromAddress::EahcRLo)?;
|
||||||
|
let charge_ah_resetable_hi = get(buf, TristarEepromAddress::EahcRHi)?;
|
||||||
|
let tenths =
|
||||||
|
u32::from(charge_ah_resetable_lo) | (u32::from(charge_ah_resetable_hi) << 16);
|
||||||
|
f64::from(tenths) * 0.1
|
||||||
|
};
|
||||||
|
|
||||||
|
let charge_ah_total = {
|
||||||
|
let charge_ah_total_lo = get(buf, TristarEepromAddress::EahcTLo)?;
|
||||||
|
let charge_ah_total_hi = get(buf, TristarEepromAddress::EahcTHi)?;
|
||||||
|
let tenths = u32::from(charge_ah_total_lo) | (u32::from(charge_ah_total_hi) << 16);
|
||||||
|
f64::from(tenths) * 0.1
|
||||||
|
};
|
||||||
|
|
||||||
|
let charge_kwh_resetable = get(buf, TristarEepromAddress::EkWhcR)?;
|
||||||
|
let charge_kwh_total = get(buf, TristarEepromAddress::EkWhcT)?;
|
||||||
|
|
||||||
|
let vb_min = scaling.get_voltage(get(buf, TristarEepromAddress::EvbMin)?);
|
||||||
|
let vb_max = scaling.get_voltage(get(buf, TristarEepromAddress::EvbMax)?);
|
||||||
|
let va_max = scaling.get_voltage(get(buf, TristarEepromAddress::EvaMax)?);
|
||||||
|
|
||||||
|
let days_since_last_equalize = get(buf, TristarEepromAddress::EtmrEqcalendar)?;
|
||||||
|
let battery_service_timer_days = get(buf, TristarEepromAddress::EtmrBattService)?;
|
||||||
|
|
||||||
|
let serial = {
|
||||||
|
let s0 = get(buf, TristarEepromAddress::Eserial0)?;
|
||||||
|
let s1 = get(buf, TristarEepromAddress::Eserial1)?;
|
||||||
|
let s2 = get(buf, TristarEepromAddress::Eserial2)?;
|
||||||
|
let s3 = get(buf, TristarEepromAddress::Eserial3)?;
|
||||||
|
|
||||||
|
let mut serial = u64::from(s0);
|
||||||
|
serial |= u64::from(s1) << 16;
|
||||||
|
serial |= u64::from(s2) << 32;
|
||||||
|
serial |= u64::from(s3) << 48;
|
||||||
|
serial
|
||||||
|
};
|
||||||
|
|
||||||
|
let model = if get(buf, TristarEepromAddress::Emodel)? == 0 {
|
||||||
|
Model::Tristar45A
|
||||||
|
} else {
|
||||||
|
Model::Tristar60A
|
||||||
|
};
|
||||||
|
|
||||||
|
let hardware_version = get(buf, TristarEepromAddress::EhwVersion)?;
|
||||||
|
|
||||||
|
ReadOnly {
|
||||||
|
hourmeter,
|
||||||
|
charge_ah_resetable,
|
||||||
|
charge_ah_total,
|
||||||
|
charge_kwh_resetable,
|
||||||
|
charge_kwh_total,
|
||||||
|
vb_min,
|
||||||
|
vb_max,
|
||||||
|
va_max,
|
||||||
|
days_since_last_equalize,
|
||||||
|
battery_service_timer_days,
|
||||||
|
serial,
|
||||||
|
model,
|
||||||
|
hardware_version,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
absorption_voltage,
|
||||||
|
float_voltage,
|
||||||
|
absorption_time_seconds,
|
||||||
|
absorption_extension_time_seconds,
|
||||||
|
absorption_extension_voltage,
|
||||||
|
float_cancel_voltage,
|
||||||
|
float_exit_timer_seconds,
|
||||||
|
equalize_voltage,
|
||||||
|
equalize_interval_days,
|
||||||
|
equalize_time_limit_above_vreg,
|
||||||
|
equalize_time_limit_at_veq,
|
||||||
|
battery_service_days,
|
||||||
|
temperature_compensation_raw,
|
||||||
|
high_voltage_disconnect,
|
||||||
|
high_voltage_reconnect,
|
||||||
|
battery_charge_reference_limit,
|
||||||
|
max_temp_comp_raw,
|
||||||
|
min_temp_comp_raw,
|
||||||
|
modbus_slave_address,
|
||||||
|
meterbus_address,
|
||||||
|
battery_current_limit,
|
||||||
|
array_target_voltage,
|
||||||
|
array_target_voltage_percentage_raw,
|
||||||
|
led_thresholds,
|
||||||
|
read_only,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
pub struct TristarState {
|
pub struct TristarState {
|
||||||
|
@ -370,6 +650,33 @@ impl Tristar {
|
||||||
Ok(new_state)
|
Ok(new_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn read_settings(&mut self) -> eyre::Result<TristarSettings> {
|
||||||
|
let network_data = self
|
||||||
|
.modbus
|
||||||
|
.read_holding_registers(NETWORK_DATA_ADDR_START, NETWORK_DATA_LENGTH)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let network = NetworkSettings::from_buf(&network_data)?;
|
||||||
|
|
||||||
|
let charge_data_1 = self
|
||||||
|
.modbus
|
||||||
|
.read_holding_registers(CHARGE_DATA_ADDR_START, 0x22)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let charge_data_2 = self
|
||||||
|
.modbus
|
||||||
|
.read_holding_registers(CHARGE_DATA_ADDR_START + 0x80, 0x4e)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut charge_data = vec![0; 0xCE];
|
||||||
|
charge_data[..0x22].copy_from_slice(&charge_data_1);
|
||||||
|
charge_data[0x80..].copy_from_slice(&charge_data_2);
|
||||||
|
|
||||||
|
let charge = ChargeSettings::from_buf(&charge_data, &self.scaling)?;
|
||||||
|
|
||||||
|
Ok(TristarSettings { network, charge })
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn set_target_voltage(&mut self, target_voltage: f64) -> eyre::Result<()> {
|
pub async fn set_target_voltage(&mut self, target_voltage: f64) -> eyre::Result<()> {
|
||||||
let scaled_voltage: u16 = self.scale_voltage(target_voltage);
|
let scaled_voltage: u16 = self.scale_voltage(target_voltage);
|
||||||
self.modbus
|
self.modbus
|
||||||
|
@ -397,6 +704,7 @@ impl Tristar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(u16)]
|
||||||
pub enum TristarRamAddress {
|
pub enum TristarRamAddress {
|
||||||
AdcVbFMed = 0x0018,
|
AdcVbFMed = 0x0018,
|
||||||
AdcVbtermF = 0x0019,
|
AdcVbtermF = 0x0019,
|
||||||
|
@ -457,6 +765,72 @@ pub enum TristarRamAddress {
|
||||||
VaRefFixedPc = 0x005B,
|
VaRefFixedPc = 0x005B,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(u16)]
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum TristarEepromAddress {
|
||||||
|
// eeprom
|
||||||
|
// tcp network settings
|
||||||
|
HTTPPort = 0x151B,
|
||||||
|
MBIPPort = 0x151C,
|
||||||
|
NetRules = 0x151D,
|
||||||
|
SNMPTrapRecPort = 0x151E,
|
||||||
|
EthernetPowerSaveMode = 0x151F,
|
||||||
|
// beta 8.21
|
||||||
|
VLANEnable = 0x1520,
|
||||||
|
VLANParameters = 0x1521,
|
||||||
|
|
||||||
|
// charge settings
|
||||||
|
EvAbsorp = 0xE000,
|
||||||
|
EvFloat = 0xE001,
|
||||||
|
EtAbsorp = 0xE002,
|
||||||
|
EtAbsorpExt = 0xE003,
|
||||||
|
EvAbsorpExt = 0xE004,
|
||||||
|
EvFloatCancel = 0xE005,
|
||||||
|
EtFloatExitCum = 0xE006,
|
||||||
|
EvEq = 0xE007,
|
||||||
|
EtEqcalendar = 0xE008,
|
||||||
|
EtEqAbove = 0xE009,
|
||||||
|
EtEqReg = 0xE00A,
|
||||||
|
EtBattService = 0xE00B,
|
||||||
|
EvTempcomp = 0xE00D,
|
||||||
|
EvHvd = 0xE00E,
|
||||||
|
EvHvr = 0xE00F,
|
||||||
|
EvbRefLim = 0xE010,
|
||||||
|
EtbMax = 0xE011,
|
||||||
|
EtbMin = 0xE012,
|
||||||
|
EvSocGGy = 0xE015,
|
||||||
|
EvSocGyY = 0xE016,
|
||||||
|
EvSocYYr = 0xE017,
|
||||||
|
EvSocYrR = 0xE018,
|
||||||
|
EmodbusId = 0xE019,
|
||||||
|
EmeterbusId = 0xE01A,
|
||||||
|
EibLim = 0xE01D,
|
||||||
|
EvaRefFixedInit = 0xE020,
|
||||||
|
EvaRefFixedPctInit = 0xE021,
|
||||||
|
|
||||||
|
// read only
|
||||||
|
EhourmeterLo = 0xE080,
|
||||||
|
EhourmeterHi = 0xE081,
|
||||||
|
EahcRLo = 0xE082,
|
||||||
|
EahcRHi = 0xE083,
|
||||||
|
EahcTLo = 0xE084,
|
||||||
|
EahcTHi = 0xE085,
|
||||||
|
EkWhcR = 0xE086,
|
||||||
|
EkWhcT = 0xE087,
|
||||||
|
EvbMin = 0xE088,
|
||||||
|
EvbMax = 0xE089,
|
||||||
|
EvaMax = 0xE08A,
|
||||||
|
EtmrEqcalendar = 0xE08B,
|
||||||
|
EtmrBattService = 0xE08C,
|
||||||
|
Eserial0 = 0xE0C0,
|
||||||
|
Eserial1 = 0xE0C1,
|
||||||
|
Eserial2 = 0xE0C2,
|
||||||
|
Eserial3 = 0xE0C3,
|
||||||
|
Emodel = 0xE0CC,
|
||||||
|
EhwVersion = 0xE0CD,
|
||||||
|
}
|
||||||
|
|
||||||
impl std::ops::Index<TristarRamAddress> for [u16] {
|
impl std::ops::Index<TristarRamAddress> for [u16] {
|
||||||
type Output = u16;
|
type Output = u16;
|
||||||
|
|
||||||
|
|
|
@ -24,12 +24,14 @@ impl AllControllers {
|
||||||
|
|
||||||
pub struct ControllerData {
|
pub struct ControllerData {
|
||||||
state: tokio::sync::RwLock<Option<crate::controller::ControllerState>>,
|
state: tokio::sync::RwLock<Option<crate::controller::ControllerState>>,
|
||||||
|
settings: tokio::sync::RwLock<Option<crate::controller::ControllerSettings>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ControllerData {
|
impl ControllerData {
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
state: tokio::sync::RwLock::const_new(None),
|
state: tokio::sync::RwLock::const_new(None),
|
||||||
|
settings: tokio::sync::RwLock::const_new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,4 +46,16 @@ impl ControllerData {
|
||||||
) -> tokio::sync::RwLockReadGuard<Option<crate::controller::ControllerState>> {
|
) -> tokio::sync::RwLockReadGuard<Option<crate::controller::ControllerState>> {
|
||||||
self.state.read().await
|
self.state.read().await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn write_settings(
|
||||||
|
&self,
|
||||||
|
) -> tokio::sync::RwLockWriteGuard<Option<crate::controller::ControllerSettings>> {
|
||||||
|
self.settings.write().await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn read_settings(
|
||||||
|
&self,
|
||||||
|
) -> tokio::sync::RwLockReadGuard<Option<crate::controller::ControllerSettings>> {
|
||||||
|
self.settings.read().await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ pub fn rocket(state: ServerState) -> rocket::Rocket<rocket::Build> {
|
||||||
interfaces,
|
interfaces,
|
||||||
all_interfaces,
|
all_interfaces,
|
||||||
all_interfaces_full,
|
all_interfaces_full,
|
||||||
|
all_interfaces_settings,
|
||||||
primary_interface,
|
primary_interface,
|
||||||
interface,
|
interface,
|
||||||
interface_full,
|
interface_full,
|
||||||
|
@ -110,6 +111,22 @@ async fn all_interfaces_full(
|
||||||
Json(data)
|
Json(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/interfaces/settings")]
|
||||||
|
async fn all_interfaces_settings(
|
||||||
|
state: &State<ServerState>,
|
||||||
|
) -> Json<Vec<(String, crate::controller::ControllerSettings)>> {
|
||||||
|
let mut data = Vec::new();
|
||||||
|
|
||||||
|
for (k, v) in state.data.all_data() {
|
||||||
|
let v = v.read_settings().await;
|
||||||
|
if let Some(v) = v.as_ref() {
|
||||||
|
data.push((k.clone(), v.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Json(data)
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/interface/<name>")]
|
#[get("/interface/<name>")]
|
||||||
async fn interface(
|
async fn interface(
|
||||||
name: &str,
|
name: &str,
|
||||||
|
|
Loading…
Add table
Reference in a new issue