275 lines
9.7 KiB
Rust
275 lines
9.7 KiB
Rust
use anyhow::bail;
|
|
use bq34z100::{Bq34Z100Error, Bq34z100g1, Bq34z100g1Driver};
|
|
use embedded_hal_bus::i2c::MutexDevice;
|
|
use esp_idf_hal::delay::Delay;
|
|
use esp_idf_hal::i2c::{I2cDriver, I2cError};
|
|
use measurements::Temperature;
|
|
use serde::Serialize;
|
|
use std::result::Result::Ok as OkStd;
|
|
use crate::to_string;
|
|
|
|
pub trait BatteryInteraction {
|
|
fn state_charge_percent(&mut self) -> anyhow::Result<u8>;
|
|
fn remaining_milli_ampere_hour(&mut self) -> anyhow::Result<u16>;
|
|
fn max_milli_ampere_hour(&mut self) -> anyhow::Result<u16>;
|
|
fn design_milli_ampere_hour(&mut self) -> anyhow::Result<u16>;
|
|
fn voltage_milli_volt(&mut self) -> anyhow::Result<u16>;
|
|
fn average_current_milli_ampere(&mut self) -> anyhow::Result<i16>;
|
|
fn cycle_count(&mut self) -> anyhow::Result<u16>;
|
|
fn state_health_percent(&mut self) -> anyhow::Result<u8>;
|
|
fn bat_temperature(&mut self) -> anyhow::Result<u16>;
|
|
fn get_battery_state(&mut self) -> String;
|
|
}
|
|
#[derive(Serialize)]
|
|
pub struct BatteryState {
|
|
voltage_milli_volt: String,
|
|
current_milli_ampere: String,
|
|
cycle_count: String,
|
|
design_milli_ampere: String,
|
|
remaining_milli_ampere: String,
|
|
state_of_charge: String,
|
|
state_of_health: String,
|
|
temperature: String,
|
|
}
|
|
pub enum BatteryMonitor<'a> {
|
|
Disabled {
|
|
|
|
},
|
|
BQ34Z100G1 {
|
|
battery_driver: Bq34z100g1Driver<MutexDevice<'a, I2cDriver<'a>>, Delay>
|
|
},
|
|
WchI2cSlave {
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl BatteryInteraction for BatteryMonitor<'_> {
|
|
fn state_charge_percent(&mut self) -> anyhow::Result<u8> {
|
|
match self {
|
|
BatteryMonitor::BQ34Z100G1 { battery_driver} => {
|
|
match battery_driver.state_of_charge() {
|
|
OkStd(r) => anyhow::Ok(r),
|
|
Err(err) => bail!("Error reading SoC {:?}", err),
|
|
}
|
|
},
|
|
BatteryMonitor::WchI2cSlave { .. } => {
|
|
bail!("Not implemented")
|
|
}
|
|
BatteryMonitor::Disabled {} => {
|
|
bail!("Battery monitor is disabled")
|
|
}
|
|
}
|
|
}
|
|
|
|
fn remaining_milli_ampere_hour(&mut self) -> anyhow::Result<u16> {
|
|
match self {
|
|
BatteryMonitor::BQ34Z100G1 { battery_driver} => {
|
|
match battery_driver.remaining_capacity(){
|
|
OkStd(r) => anyhow::Ok(r),
|
|
Err(err) => bail!("Error reading remaining_milli_ampere_hour {:?}", err),
|
|
}
|
|
},
|
|
BatteryMonitor::WchI2cSlave { .. } => {
|
|
bail!("Not implemented")
|
|
},
|
|
&mut BatteryMonitor::Disabled { } => {
|
|
bail!("Battery monitor is disabled")
|
|
}
|
|
}
|
|
}
|
|
fn max_milli_ampere_hour(&mut self) -> anyhow::Result<u16> {
|
|
match self {
|
|
BatteryMonitor::BQ34Z100G1 { battery_driver} => {
|
|
match battery_driver.full_charge_capacity() {
|
|
OkStd(r) => anyhow::Ok(r),
|
|
Err(err) => bail!("Error reading max_milli_ampere_hour {:?}", err),
|
|
}
|
|
},
|
|
BatteryMonitor::WchI2cSlave { .. } => {
|
|
bail!("Not implemented")
|
|
},
|
|
&mut BatteryMonitor::Disabled { } => {
|
|
bail!("Battery monitor is disabled")
|
|
}
|
|
}
|
|
}
|
|
fn design_milli_ampere_hour(&mut self) -> anyhow::Result<u16> {
|
|
match self {
|
|
BatteryMonitor::BQ34Z100G1 { battery_driver} => {
|
|
match battery_driver.design_capacity() {
|
|
OkStd(r) => anyhow::Ok(r),
|
|
Err(err) => bail!("Error reading design_milli_ampere_hour {:?}", err),
|
|
}
|
|
},
|
|
BatteryMonitor::WchI2cSlave { .. } => {
|
|
bail!("Not implemented")
|
|
},
|
|
&mut BatteryMonitor::Disabled { } => {
|
|
bail!("Battery monitor is disabled")
|
|
}
|
|
}
|
|
}
|
|
fn voltage_milli_volt(&mut self) -> anyhow::Result<u16> {
|
|
match self {
|
|
BatteryMonitor::BQ34Z100G1 { battery_driver} => {
|
|
match battery_driver.voltage() {
|
|
OkStd(r) => anyhow::Ok(r),
|
|
Err(err) => bail!("Error reading voltage_milli_volt {:?}", err),
|
|
}
|
|
},
|
|
BatteryMonitor::WchI2cSlave { .. } => {
|
|
bail!("Not implemented")
|
|
},
|
|
&mut BatteryMonitor::Disabled { } => {
|
|
bail!("Battery monitor is disabled")
|
|
}
|
|
}
|
|
}
|
|
fn average_current_milli_ampere(&mut self) -> anyhow::Result<i16> {
|
|
match self {
|
|
BatteryMonitor::BQ34Z100G1 { battery_driver} => {
|
|
match battery_driver.average_current() {
|
|
OkStd(r) => anyhow::Ok(r),
|
|
Err(err) => bail!("Error reading average_current_milli_ampere {:?}", err),
|
|
}
|
|
},
|
|
BatteryMonitor::WchI2cSlave { .. } => {
|
|
bail!("Not implemented")
|
|
},
|
|
&mut BatteryMonitor::Disabled { } => {
|
|
bail!("Battery monitor is disabled")
|
|
}
|
|
}
|
|
}
|
|
fn cycle_count(&mut self) -> anyhow::Result<u16> {
|
|
match self {
|
|
BatteryMonitor::BQ34Z100G1 { battery_driver} => {
|
|
match battery_driver.cycle_count() {
|
|
OkStd(r) => anyhow::Ok(r),
|
|
Err(err) => bail!("Error reading cycle_count {:?}", err),
|
|
}
|
|
},
|
|
BatteryMonitor::WchI2cSlave { .. } => {
|
|
bail!("Not implemented")
|
|
},
|
|
&mut BatteryMonitor::Disabled { } => {
|
|
bail!("Battery monitor is disabled")
|
|
}
|
|
}
|
|
}
|
|
fn state_health_percent(&mut self) -> anyhow::Result<u8> {
|
|
match self {
|
|
BatteryMonitor::BQ34Z100G1 { battery_driver} => {
|
|
match battery_driver.state_of_health() {
|
|
OkStd(r) => anyhow::Ok(r as u8),
|
|
Err(err) => bail!("Error reading state_health_percent {:?}", err),
|
|
}
|
|
},
|
|
BatteryMonitor::WchI2cSlave { .. } => {
|
|
bail!("Not implemented")
|
|
},
|
|
&mut BatteryMonitor::Disabled { } => {
|
|
bail!("Battery monitor is disabled")
|
|
}
|
|
}
|
|
}
|
|
fn bat_temperature(&mut self) -> anyhow::Result<u16> {
|
|
match self {
|
|
BatteryMonitor::BQ34Z100G1 { battery_driver} => {
|
|
match battery_driver.temperature() {
|
|
OkStd(r) => anyhow::Ok(r),
|
|
Err(err) => bail!("Error reading bat_temperature {:?}", err),
|
|
}
|
|
},
|
|
BatteryMonitor::WchI2cSlave { .. } => {
|
|
bail!("Not implemented")
|
|
},
|
|
&mut BatteryMonitor::Disabled { } => {
|
|
bail!("Battery monitor is disabled")
|
|
}
|
|
}
|
|
}
|
|
|
|
fn get_battery_state(&mut self) -> String {
|
|
let bat = BatteryState {
|
|
voltage_milli_volt: to_string(self.voltage_milli_volt()),
|
|
current_milli_ampere: to_string(self.average_current_milli_ampere()),
|
|
cycle_count: to_string(self.cycle_count()),
|
|
design_milli_ampere: to_string(self.design_milli_ampere_hour()),
|
|
remaining_milli_ampere: to_string(self.remaining_milli_ampere_hour()),
|
|
state_of_charge: to_string(self.state_charge_percent()),
|
|
state_of_health: to_string(self.state_health_percent()),
|
|
temperature: to_string(self.bat_temperature()),
|
|
};
|
|
|
|
match serde_json::to_string(&bat) {
|
|
Ok(state) => {
|
|
state
|
|
}
|
|
Err(err) => {
|
|
format!("{:?}", err).to_owned()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn print_battery_bq34z100(
|
|
battery_driver: &mut Bq34z100g1Driver<MutexDevice<I2cDriver<'_>>, Delay>,
|
|
) -> anyhow::Result<(), Bq34Z100Error<I2cError>> {
|
|
println!("Try communicating with battery");
|
|
let fwversion = battery_driver.fw_version().unwrap_or_else(|e| {
|
|
println!("Firmware {:?}", e);
|
|
0
|
|
});
|
|
println!("fw version is {}", fwversion);
|
|
|
|
let design_capacity = battery_driver.design_capacity().unwrap_or_else(|e| {
|
|
println!("Design capacity {:?}", e);
|
|
0
|
|
});
|
|
println!("Design Capacity {}", design_capacity);
|
|
if design_capacity == 1000 {
|
|
println!("Still stock configuring battery, readouts are likely to be wrong!");
|
|
}
|
|
|
|
let flags = battery_driver.get_flags_decoded()?;
|
|
println!("Flags {:?}", flags);
|
|
|
|
let chem_id = battery_driver.chem_id().unwrap_or_else(|e| {
|
|
println!("Chemid {:?}", e);
|
|
0
|
|
});
|
|
|
|
let bat_temp = battery_driver.internal_temperature().unwrap_or_else(|e| {
|
|
println!("Bat Temp {:?}", e);
|
|
0
|
|
});
|
|
let temp_c = Temperature::from_kelvin(bat_temp as f64 / 10_f64).as_celsius();
|
|
let voltage = battery_driver.voltage().unwrap_or_else(|e| {
|
|
println!("Bat volt {:?}", e);
|
|
0
|
|
});
|
|
let current = battery_driver.current().unwrap_or_else(|e| {
|
|
println!("Bat current {:?}", e);
|
|
0
|
|
});
|
|
let state = battery_driver.state_of_charge().unwrap_or_else(|e| {
|
|
println!("Bat Soc {:?}", e);
|
|
0
|
|
});
|
|
let charge_voltage = battery_driver.charge_voltage().unwrap_or_else(|e| {
|
|
println!("Bat Charge Volt {:?}", e);
|
|
0
|
|
});
|
|
let charge_current = battery_driver.charge_current().unwrap_or_else(|e| {
|
|
println!("Bat Charge Current {:?}", e);
|
|
0
|
|
});
|
|
println!("ChemId: {} Current voltage {} and current {} with charge {}% and temp {} CVolt: {} CCur {}", chem_id, voltage, current, state, temp_c, charge_voltage, charge_current);
|
|
let _ = battery_driver.unsealed();
|
|
let _ = battery_driver.it_enable();
|
|
anyhow::Result::Ok(())
|
|
}
|