From 1abad4da7b0e486a6cde5532b83335d5b7bedd4f Mon Sep 17 00:00:00 2001 From: PurpleWazard <155469001+PurpleWazard@users.noreply.github.com> Date: Tue, 6 Feb 2024 23:27:56 -0600 Subject: [PATCH] Add battery charge thresholds limit (#637) * added battery files * finished main battery script * added battery_script in auto_cpufreq * fix some errors with batterys * setup some battery stat printing * added battery config printing to monitor and live modes * fix some bugs now works on daemon and monitor mode * cleaned up battery.py * started to fix writing issue * still debuging fixes * bug fixed thinkpad stop threshold cant do below 65 * updated auto-cpufreq.conf-example with battery thresholds --- auto-cpufreq.conf-example | 14 ++++++ auto_cpufreq/battery_scripts/battery.py | 60 ++++++++++++++++++++++++ auto_cpufreq/battery_scripts/ideapad.py | 44 +++++++++++++++++ auto_cpufreq/battery_scripts/thinkpad.py | 51 ++++++++++++++++++++ auto_cpufreq/bin/auto_cpufreq.py | 6 ++- 5 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 auto_cpufreq/battery_scripts/battery.py create mode 100644 auto_cpufreq/battery_scripts/ideapad.py create mode 100644 auto_cpufreq/battery_scripts/thinkpad.py diff --git a/auto-cpufreq.conf-example b/auto-cpufreq.conf-example index 3ede8ae5..86afa584 100644 --- a/auto-cpufreq.conf-example +++ b/auto-cpufreq.conf-example @@ -45,3 +45,17 @@ energy_performance_preference = power # turbo boost setting. possible values: always, auto, never turbo = auto + +# experimental + +# Add battery charging threshold (currently only available to Lenovo) +# checkout README.md for more info + +# enable thresholds true or false +#enable_thresholds = true +# +# start threshold (defaults to 0 ) can be 0 - 100 +#start_threshold = 0 +# +# stop threshold (defaults to 100) this value must be greater or equal to 65 +#stop_threshold = 100 diff --git a/auto_cpufreq/battery_scripts/battery.py b/auto_cpufreq/battery_scripts/battery.py new file mode 100644 index 00000000..871863d4 --- /dev/null +++ b/auto_cpufreq/battery_scripts/battery.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +import subprocess +from auto_cpufreq.core import get_config, root_check + +from auto_cpufreq.battery_scripts.thinkpad import * +from auto_cpufreq.battery_scripts.ideapad import * + + +def lsmod(module): + output = subprocess.run(['lsmod'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + if module in output.stdout: + return True + else: + return False + + +def battery_start_threshold(): + conf = get_config() + if conf.has_option("battery", "start_threshold"): + start_threshold = conf["battery"]["start_threshold"] + return int(start_threshold) + else: + return 0 + + +def battery_stop_threshold(): + conf = get_config() + if conf.has_option("battery", "stop_threshold"): + stop_threshold = conf["battery"]["stop_threshold"] + return int(stop_threshold) + else: + return 100 + + +def battery_setup(): + root_check() + conf = get_config() + if conf.has_option("battery", "enable_thresholds") and conf["battery"]["enable_thresholds"] == "true": + if lsmod("thinkpad_acpi"): + thinkpad_setup(battery_start_threshold(), battery_stop_threshold()) + elif lsmod("ideapad_acpi"): + ideapad_setup(battery_start_threshold(), battery_stop_threshold()) + else: + pass + else: + pass + + +def battery_get_thresholds(): + conf = get_config() + if conf["battery"]["enable_thresholds"] == "true": + print("-" * 30) + if lsmod("thinkpad_acpi"): + thinkpad_print_thresholds() + elif lsmod("ideapad_acpi"): + ideapad_print_thresholds() + else: + pass + else: + return diff --git a/auto_cpufreq/battery_scripts/ideapad.py b/auto_cpufreq/battery_scripts/ideapad.py new file mode 100644 index 00000000..5f078219 --- /dev/null +++ b/auto_cpufreq/battery_scripts/ideapad.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +import os +from auto_cpufreq.core import root_check + + +def ideapad_setup(start_threshold, stop_threshold): + root_check() + # this path is specific to ideapads + path_to_bats = '/sys/class/power_supply/' + # gets the numb of batteries + battery_count = len([name for name in os.listdir(path_to_bats) if name.startswith('BAT')]) + + for b in range(battery_count): + + try: + with open(f'{path_to_bats}BAT{b}/charge_start_threshold', 'w') as f: + f.write(str(start_threshold) + '\n') + f.close() + + with open(f'{path_to_bats}BAT{b}/charge_stop_threshold', 'w') as f: + f.write(str(stop_threshold) + '\n') + f.close() + + except Exception: + pass + + +def ideapad_print_thresholds(): + root_check() + path_to_bats = '/sys/class/power_supply/' + battery_count = len([name for name in os.listdir(path_to_bats) if name.startswith('BAT')]) + print(f"number of batteries = {battery_count}") + for b in range(battery_count): + try: + with open(f'{path_to_bats}BAT{b}/charge_start_threshold', 'r') as f: + print(f'battery{b} start threshold is set to {f.read()}') + f.close() + + with open(f'{path_to_bats}BAT{b}/charge_stop_threshold', 'r') as f: + print(f'battery{b} stop threshold is set to {f.read()}') + f.close() + + except Exception as e: + print(f"Error reading battery thresholds: {e}") diff --git a/auto_cpufreq/battery_scripts/thinkpad.py b/auto_cpufreq/battery_scripts/thinkpad.py new file mode 100644 index 00000000..23270914 --- /dev/null +++ b/auto_cpufreq/battery_scripts/thinkpad.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +import os +from auto_cpufreq.core import root_check + + +def thinkpad_setup(start_threshold, stop_threshold): + root_check() + # this path is specific to thinkpads + path_to_bats = '/sys/class/power_supply/' + # gets the numb of batteries + battery_count = len([name for name in os.listdir(path_to_bats) if name.startswith('BAT')]) + + for b in range(battery_count): + + try: + with open(f'{path_to_bats}BAT{b}/charge_start_threshold', 'w') as f: + f.write(str(start_threshold) + '\n') + f.close() + except Exception as e: + print(f"could not write to BAT{b} start threshold") + print(e) + + try: + with open(f'{path_to_bats}BAT{b}/charge_stop_threshold', 'w') as f: + f.write(str(stop_threshold) + '\n') + f.close() + + except Exception as e: + print(f"could not write to BAT{b} stop threshold you might be setting it too low try < 65") + print(e) + pass + + +def thinkpad_print_thresholds(): + root_check() + # this path is specific to thinkpads + path_to_bats = '/sys/class/power_supply/' + battery_count = len([name for name in os.listdir(path_to_bats) if name.startswith('BAT')]) + print(f"number of batteries = {battery_count}") + for b in range(battery_count): + try: + with open(f'{path_to_bats}BAT{b}/charge_start_threshold', 'r') as f: + print(f'battery{b} start threshold is set to {f.read()}') + f.close() + + with open(f'{path_to_bats}BAT{b}/charge_stop_threshold', 'r') as f: + print(f'battery{b} stop threshold is set to {f.read()}') + f.close() + + except Exception as e: + print(f"Error reading battery thresholds: {e}") diff --git a/auto_cpufreq/bin/auto_cpufreq.py b/auto_cpufreq/bin/auto_cpufreq.py index db2b84da..50056489 100755 --- a/auto_cpufreq/bin/auto_cpufreq.py +++ b/auto_cpufreq/bin/auto_cpufreq.py @@ -13,7 +13,7 @@ # sys.path.append("../") from auto_cpufreq.core import * from auto_cpufreq.power_helper import * - +from auto_cpufreq.battery_scripts.battery import * # cli @click.command() @click.option("--monitor", is_flag=True, help="Monitor and see suggestions for CPU optimizations") @@ -67,6 +67,7 @@ def config_info_dialog(): if os.getenv("PKG_MARKER") == "SNAP" and dcheck == "enabled": gnome_power_detect_snap() tlp_service_detect_snap() + battery_setup() while True: footer() gov_check() @@ -78,6 +79,7 @@ def config_info_dialog(): elif os.getenv("PKG_MARKER") != "SNAP": gnome_power_detect() tlp_service_detect() + battery_setup() while True: footer() gov_check() @@ -94,6 +96,8 @@ def config_info_dialog(): config_info_dialog() root_check() print('\nNote: You can quit monitor mode by pressing "ctrl+c"') + battery_setup() + battery_get_thresholds() if os.getenv("PKG_MARKER") == "SNAP": gnome_power_detect_snap() tlp_service_detect_snap()