100 lines
3.0 KiB
Rust
100 lines
3.0 KiB
Rust
use crate::fat_error::{FatError, FatResult};
|
|
use crate::hal::Box;
|
|
use async_trait::async_trait;
|
|
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
|
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
|
use esp_hal::i2c::master::I2c;
|
|
use esp_hal::Blocking;
|
|
use lib_bms_protocol::{
|
|
BatteryState as bstate, BmsReadable, Config, FirmwareVersion, ProtocolVersion,
|
|
};
|
|
use serde::Serialize;
|
|
|
|
#[async_trait(?Send)]
|
|
pub trait BatteryInteraction {
|
|
async fn get_state(&mut self) -> FatResult<BatteryState>;
|
|
async fn get_firmware(&mut self) -> FatResult<FirmwareVersion>;
|
|
async fn get_protocol(&mut self) -> FatResult<ProtocolVersion>;
|
|
async fn reset(&mut self) -> FatResult<()>;
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Copy, Clone)]
|
|
pub struct BatteryInfo {
|
|
pub voltage_milli_volt: u32,
|
|
pub average_current_milli_ampere: i32,
|
|
pub design_milli_ampere_hour: u32,
|
|
pub remaining_milli_ampere_hour: u32,
|
|
pub state_of_charge: u8,
|
|
pub state_of_health: u32,
|
|
pub temperature: i32,
|
|
}
|
|
|
|
#[derive(Debug, Serialize)]
|
|
pub enum BatteryState {
|
|
Unknown,
|
|
Info(BatteryInfo),
|
|
}
|
|
|
|
/// If no battery monitor is installed this implementation will be used
|
|
pub struct NoBatteryMonitor {}
|
|
#[async_trait(?Send)]
|
|
impl BatteryInteraction for NoBatteryMonitor {
|
|
async fn get_state(&mut self) -> FatResult<BatteryState> {
|
|
Ok(BatteryState::Unknown)
|
|
}
|
|
|
|
async fn get_firmware(&mut self) -> FatResult<FirmwareVersion> {
|
|
Err(FatError::NoBatteryMonitor)
|
|
}
|
|
|
|
async fn get_protocol(&mut self) -> FatResult<ProtocolVersion> {
|
|
Err(FatError::NoBatteryMonitor)
|
|
}
|
|
|
|
async fn reset(&mut self) -> FatResult<()> {
|
|
Err(FatError::NoBatteryMonitor)
|
|
}
|
|
}
|
|
|
|
//TODO implement this battery monitor kind once controller is complete
|
|
#[allow(dead_code)]
|
|
pub struct WchI2cSlave {}
|
|
|
|
pub struct WCHI2CSlave<'a> {
|
|
pub(crate) i2c: I2cDevice<'a, CriticalSectionRawMutex, I2c<'a, Blocking>>,
|
|
}
|
|
|
|
#[async_trait(?Send)]
|
|
impl BatteryInteraction for WCHI2CSlave<'_> {
|
|
async fn get_state(&mut self) -> FatResult<BatteryState> {
|
|
let state = bstate::read_from_i2c(&mut self.i2c)?;
|
|
let config = Config::read_from_i2c(&mut self.i2c)?;
|
|
|
|
let state_of_charge =
|
|
(state.remaining_capacity_mah * 100 / state.lifetime_capacity_mah) as u8;
|
|
let state_of_health = state.lifetime_capacity_mah / config.capacity_mah * 100;
|
|
|
|
Ok(BatteryState::Info(BatteryInfo {
|
|
voltage_milli_volt: state.current_mv,
|
|
average_current_milli_ampere: 1337,
|
|
design_milli_ampere_hour: config.capacity_mah,
|
|
remaining_milli_ampere_hour: state.remaining_capacity_mah,
|
|
state_of_charge,
|
|
state_of_health,
|
|
temperature: state.temperature_celcius,
|
|
}))
|
|
}
|
|
|
|
async fn get_firmware(&mut self) -> FatResult<FirmwareVersion> {
|
|
todo!()
|
|
}
|
|
|
|
async fn get_protocol(&mut self) -> FatResult<ProtocolVersion> {
|
|
todo!()
|
|
}
|
|
|
|
async fn reset(&mut self) -> FatResult<()> {
|
|
todo!()
|
|
}
|
|
}
|