~loshz/chargectl

203cc628f8b4861d887b7edbdd5d9ce78f4beceb — Dan Bond a month ago d2d48be main 0.2.0
prep 0.2.0

Signed-off-by: Dan Bond <danbond@protonmail.com>
5 files changed, 39 insertions(+), 60 deletions(-)

M Cargo.lock
M Cargo.toml
M src/cli.rs
M src/error.rs
M src/sysfs.rs
M Cargo.lock => Cargo.lock +19 -19
@@ 4,22 4,22 @@ version = 3

[[package]]
name = "anstyle"
version = "1.0.7"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"

[[package]]
name = "chargectl"
version = "0.1.1"
version = "0.2.0"
dependencies = [
 "clap",
]

[[package]]
name = "clap"
version = "4.5.9"
version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462"
checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
dependencies = [
 "clap_builder",
 "clap_derive",


@@ 27,9 27,9 @@ dependencies = [

[[package]]
name = "clap_builder"
version = "4.5.9"
version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942"
checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
dependencies = [
 "anstyle",
 "clap_lex",


@@ 37,9 37,9 @@ dependencies = [

[[package]]
name = "clap_derive"
version = "4.5.8"
version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085"
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
dependencies = [
 "heck",
 "proc-macro2",


@@ 49,9 49,9 @@ dependencies = [

[[package]]
name = "clap_lex"
version = "0.7.1"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"

[[package]]
name = "heck"


@@ 61,27 61,27 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"

[[package]]
name = "proc-macro2"
version = "1.0.86"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
dependencies = [
 "unicode-ident",
]

[[package]]
name = "quote"
version = "1.0.36"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
 "proc-macro2",
]

[[package]]
name = "syn"
version = "2.0.71"
version = "2.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462"
checksum = "e89275301d38033efb81a6e60e3497e734dfcc62571f2854bf4b16690398824c"
dependencies = [
 "proc-macro2",
 "quote",


@@ 90,6 90,6 @@ dependencies = [

[[package]]
name = "unicode-ident"
version = "1.0.12"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"

M Cargo.toml => Cargo.toml +1 -1
@@ 1,6 1,6 @@
[package]
name = "chargectl"
version = "0.1.1"
version = "0.2.0"
authors = ["Dan Bond <danbond@protonmail.com>"]
edition = "2021"
rust-version = "1.72"

M src/cli.rs => src/cli.rs +2 -5
@@ 17,7 17,7 @@ enum Commands {
    /// Set thresholds to enable immediate charging until full
    Full(Battery),

    /// Get the current start and stop thresholds for a given battery
    /// Get current start and stop thresholds for a given battery
    Get(Battery),

    /// Set start and stop charge thresholds for a given battery


@@ 47,10 47,7 @@ struct Battery {
impl Chargectl {
    pub fn run(self) -> Result<(), ChargeError> {
        match self.command {
            Commands::Full(args) => {
                sysfs::is_ac_power_online()?;
                sysfs::set_thresholds(96, 100, args.battery)
            }
            Commands::Full(args) => sysfs::set_thresholds(96, 100, args.battery),
            Commands::Get(args) => sysfs::get_thresholds(args.battery),
            Commands::Set(args) => sysfs::set_thresholds(args.start, args.stop, args.battery),
        }

M src/error.rs => src/error.rs +12 -18
@@ 7,7 7,6 @@ use crate::sysfs;
// Wrapped operation errors.
#[derive(Debug)]
pub enum ChargeError {
    AC,
    Battery(OsString),
    IO(std::io::Error),
    Unsupported,


@@ 16,34 15,29 @@ pub enum ChargeError {

impl fmt::Display for ChargeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let description: String = match self {
            ChargeError::AC => "AC power is not connected".to_string(),
            ChargeError::Battery(bat) => format!("battery not found: {:?}", bat),
            ChargeError::IO(err) => {
        let description = match self {
            Self::Battery(bat) => &format!("battery not found: {:?}", bat),
            Self::IO(err) => {
                match err.kind() {
                    // Usually fixed by running sudo.
                    ErrorKind::PermissionDenied => {
                        "permission denied, try running the same command with sudo privileges"
                            .to_string()
                    }
                    // If we already know that the power supply class in sysfs exists, then this file
                    // _should_ exist.
                    ErrorKind::NotFound => {
                        format!(
                            "battery thresholds not found {:?}",
                            sysfs::CLASS_POWER_SUPPLY
                        )
                    }
                    ErrorKind::NotFound => &format!(
                        "battery thresholds not found {:?}",
                        sysfs::CLASS_POWER_SUPPLY
                    ),
                    // Generic catch-all error.
                    _ => format!("failed to write charge threshold: {err}"),
                    _ => &format!("failed to write charge threshold: {err}"),
                }
            }
            ChargeError::Unsupported => "unsupported platform".to_string(),
            ChargeError::Threshold => {
                "thresholds must be numerical [1-100], and start < stop".to_string()
            }
            Self::Unsupported => "unsupported platform",
            Self::Threshold => "thresholds must be numerical [1-100], and start < stop",
        };
        f.write_str(description.as_str())

        f.write_str(description)
    }
}


M src/sysfs.rs => src/sysfs.rs +5 -17
@@ 26,26 26,14 @@ pub fn is_platform_supported() -> Result<(), ChargeError> {
    Ok(())
}

// Check sysfs to see if AC power is online.
pub fn is_ac_power_online() -> Result<(), ChargeError> {
    let sysfs_ac = Path::new(CLASS_POWER_SUPPLY).join("AC/online");
    let online = read_threshold(sysfs_ac)?;
    if online == 0 {
        return Err(ChargeError::AC);
    }

    Ok(())
}

// Construct a sysfs path for a given battery.
pub fn get_battery_path(battery: Option<OsString>) -> Result<PathBuf, ChargeError> {
    // Set battery default if not specified.
    let bat: OsString = match battery {
        Some(b) => b.to_ascii_uppercase(),
        None => DEFAULT_BATTERY.into(),
    };
    let bat: OsString = battery
        .unwrap_or(DEFAULT_BATTERY.into())
        .to_ascii_uppercase();

    let sysfs_bat = Path::new(CLASS_POWER_SUPPLY).join(bat.clone());
    let sysfs_bat = Path::new(CLASS_POWER_SUPPLY).join(&bat);
    if !sysfs_bat.exists() {
        return Err(ChargeError::Battery(bat));
    }


@@ 149,7 137,7 @@ pub fn read_threshold(path: PathBuf) -> Result<u8, ChargeError> {

#[cfg(test)]
mod tests {
    use super::*;
    use super::validate_thresholds;

    #[test]
    fn test_validate_thresholds() {