use crate::{HardwareQueryError, Result};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum BatteryStatus {
Charging,
Discharging,
Full,
NotCharging,
Unknown,
}
impl std::fmt::Display for BatteryStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
BatteryStatus::Charging => write!(f, "Charging"),
BatteryStatus::Discharging => write!(f, "Discharging"),
BatteryStatus::Full => write!(f, "Full"),
BatteryStatus::NotCharging => write!(f, "Not Charging"),
BatteryStatus::Unknown => write!(f, "Unknown"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BatteryInfo {
pub percentage: f32,
pub status: BatteryStatus,
pub time_remaining_minutes: Option<u32>,
pub health_percent: Option<f32>,
pub design_capacity_wh: Option<f32>,
pub current_capacity_wh: Option<f32>,
pub cycle_count: Option<u32>,
pub temperature: Option<f32>,
pub voltage: Option<f32>,
pub current: Option<f32>,
pub manufacturer: Option<String>,
pub model: Option<String>,
pub serial_number: Option<String>,
}
impl BatteryInfo {
pub fn query() -> Result<Self> {
Err(HardwareQueryError::device_not_found("No battery detected"))
}
pub fn percentage(&self) -> f32 {
self.percentage
}
pub fn status(&self) -> &BatteryStatus {
&self.status
}
pub fn is_charging(&self) -> bool {
matches!(self.status, BatteryStatus::Charging)
}
pub fn is_discharging(&self) -> bool {
matches!(self.status, BatteryStatus::Discharging)
}
pub fn time_remaining_hours(&self) -> Option<f32> {
self.time_remaining_minutes
.map(|minutes| minutes as f32 / 60.0)
}
pub fn health_percent(&self) -> Option<f32> {
self.health_percent
}
pub fn wear_percent(&self) -> Option<f32> {
match (self.design_capacity_wh, self.current_capacity_wh) {
(Some(design), Some(current)) if design > 0.0 => {
Some(((design - current) / design) * 100.0)
}
_ => None,
}
}
pub fn needs_replacement(&self) -> bool {
if let Some(health) = self.health_percent {
health < 80.0
} else if let Some(wear) = self.wear_percent() {
wear > 20.0
} else {
false
}
}
pub fn capacity_wh(&self) -> Option<f32> {
self.current_capacity_wh
}
pub fn charge_percent(&self) -> f32 {
self.percentage
}
}