-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: user defined battery curve (#110)
* chore: battery curve * feat: user defined battery curve
- Loading branch information
Showing
8 changed files
with
301 additions
and
232 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
use std::{ | ||
fs::{File, OpenOptions}, | ||
io::{self, Read, Write}, | ||
path::Path, | ||
}; | ||
|
||
use chrono::{DateTime, Local}; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
/// Battery voltage threshold, (low, percentage at low) | ||
pub type BatteryThreshold = (f32, f32); | ||
|
||
fn default_i2c_bus() -> u8 { | ||
1 | ||
} | ||
|
||
/// Default auth session timeout, 1h | ||
fn default_session_timeout() -> u32 { | ||
60 * 60 | ||
} | ||
|
||
/// PiSugar configuration | ||
#[derive(Clone, Serialize, Deserialize)] | ||
pub struct PiSugarConfig { | ||
/// Http digest auth | ||
#[serde(default)] | ||
pub auth_user: Option<String>, | ||
|
||
#[serde(default)] | ||
pub auth_password: Option<String>, | ||
|
||
/// Auth session timeout in seconds | ||
#[serde(default = "default_session_timeout")] | ||
pub session_timeout: u32, | ||
|
||
/// I2C bus, default 1 (/dev/i2c-1) | ||
#[serde(default = "default_i2c_bus")] | ||
pub i2c_bus: u8, | ||
|
||
/// I2C addr, default 0x57 (87), available in PiSugar3 | ||
#[serde(default)] | ||
pub i2c_addr: Option<u16>, | ||
|
||
/// Alarm time | ||
#[serde(default)] | ||
pub auto_wake_time: Option<DateTime<Local>>, | ||
|
||
/// Alarm weekday repeat | ||
#[serde(default)] | ||
pub auto_wake_repeat: u8, | ||
|
||
/// Single tap enable | ||
#[serde(default)] | ||
pub single_tap_enable: bool, | ||
|
||
/// Single tap shell script | ||
#[serde(default)] | ||
pub single_tap_shell: String, | ||
|
||
/// Double tap enable | ||
#[serde(default)] | ||
pub double_tap_enable: bool, | ||
|
||
/// Double tap shell script | ||
#[serde(default)] | ||
pub double_tap_shell: String, | ||
|
||
/// Long tap enable | ||
#[serde(default)] | ||
pub long_tap_enable: bool, | ||
|
||
/// Long tap shell script | ||
#[serde(default)] | ||
pub long_tap_shell: String, | ||
|
||
/// Auto shutdown when battery level is low | ||
#[serde(default)] | ||
pub auto_shutdown_level: Option<f64>, | ||
|
||
/// Auto shutdown delay, seconds | ||
#[serde(default)] | ||
pub auto_shutdown_delay: Option<f64>, | ||
|
||
/// Charging range | ||
#[serde(default)] | ||
pub auto_charging_range: Option<(f32, f32)>, | ||
|
||
/// Keep charging duration | ||
#[serde(default)] | ||
pub full_charge_duration: Option<u64>, | ||
|
||
/// UPS automatically power on when power recovered | ||
#[serde(default)] | ||
pub auto_power_on: Option<bool>, | ||
|
||
/// Soft poweroff, PiSugar 3 only | ||
#[serde(default)] | ||
pub soft_poweroff: Option<bool>, | ||
|
||
/// Soft poweroff shell script | ||
#[serde(default)] | ||
pub soft_poweroff_shell: Option<String>, | ||
|
||
/// Auto rtc sync | ||
#[serde(default)] | ||
pub auto_rtc_sync: Option<bool>, | ||
|
||
/// RTC ppm adjust comm (every second) | ||
#[serde(default)] | ||
pub adj_comm: Option<u8>, | ||
|
||
/// RTC ppm adjust diff (in 31s) | ||
#[serde(default)] | ||
pub adj_diff: Option<u8>, | ||
|
||
/// RTC adjust ppm | ||
#[serde(default)] | ||
pub rtc_adj_ppm: Option<f64>, | ||
|
||
/// Anti mistouch | ||
#[serde(default)] | ||
pub anti_mistouch: Option<bool>, | ||
|
||
/// Battery hardware protect | ||
#[serde(default)] | ||
pub bat_protect: Option<bool>, | ||
|
||
/// User defined battery curve | ||
#[serde(default)] | ||
pub battery_curve: Option<Vec<BatteryThreshold>>, | ||
} | ||
|
||
impl PiSugarConfig { | ||
fn _validate_battery_curve(cfg: &PiSugarConfig) -> bool { | ||
let mut curve = cfg.battery_curve.clone().unwrap_or_default(); | ||
curve.sort_by(|x, y| x.0.total_cmp(&y.0)); | ||
for i in 1..curve.len() { | ||
if curve[i].0 == curve[i - 1].0 || curve[i].1 <= curve[i - 1].1 { | ||
log::error!("Invalid customized battery curve {:?} {:?}", curve[i - 1], curve[i]); | ||
return false; | ||
} | ||
} | ||
true | ||
} | ||
|
||
pub fn load(&mut self, path: &Path) -> io::Result<()> { | ||
let mut f = File::open(path)?; | ||
let mut buff = String::new(); | ||
let _ = f.read_to_string(&mut buff)?; | ||
let config = serde_json::from_str(&buff)?; | ||
if !PiSugarConfig::_validate_battery_curve(&config) { | ||
return Err(io::ErrorKind::InvalidData.into()); | ||
} | ||
*self = config; | ||
Ok(()) | ||
} | ||
|
||
pub fn save_to(&self, path: &Path) -> io::Result<()> { | ||
let mut options = OpenOptions::new(); | ||
options.write(true).create(true); | ||
let mut f = options.open(path)?; | ||
let s = serde_json::to_string_pretty(self)?; | ||
log::info!("Dump config:\n{}", s); | ||
f.set_len(0)?; | ||
f.write_all(s.as_bytes()) | ||
} | ||
} | ||
|
||
impl Default for PiSugarConfig { | ||
fn default() -> Self { | ||
Self { | ||
auth_user: Default::default(), | ||
auth_password: Default::default(), | ||
session_timeout: default_session_timeout(), | ||
i2c_bus: default_i2c_bus(), | ||
i2c_addr: Default::default(), | ||
auto_wake_time: Default::default(), | ||
auto_wake_repeat: Default::default(), | ||
single_tap_enable: Default::default(), | ||
single_tap_shell: Default::default(), | ||
double_tap_enable: Default::default(), | ||
double_tap_shell: Default::default(), | ||
long_tap_enable: Default::default(), | ||
long_tap_shell: Default::default(), | ||
auto_shutdown_level: Default::default(), | ||
auto_shutdown_delay: Default::default(), | ||
auto_charging_range: Default::default(), | ||
full_charge_duration: Default::default(), | ||
auto_power_on: Default::default(), | ||
soft_poweroff: Default::default(), | ||
soft_poweroff_shell: Default::default(), | ||
auto_rtc_sync: Default::default(), | ||
adj_comm: Default::default(), | ||
adj_diff: Default::default(), | ||
rtc_adj_ppm: Default::default(), | ||
anti_mistouch: Default::default(), | ||
bat_protect: Default::default(), | ||
battery_curve: Default::default(), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.