Skip to content

Commit

Permalink
implement more tolerant battery detection
Browse files Browse the repository at this point in the history
Signed-off-by: Sujal Singh <email.sujalsingh@gmail.com>
  • Loading branch information
sujaldev committed Feb 2, 2024
1 parent 2f1cd0c commit 93eeaa9
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 6 deletions.
7 changes: 7 additions & 0 deletions CREDITS
Original file line number Diff line number Diff line change
Expand Up @@ -821,3 +821,10 @@ I: 2222
N: Ryan Carsten Schmidt
W: https://github.com/ryandesign
I: 2361

N: Sujal Singh
E: git@sujal.dev
W: https://sujal.dev
C: India
D: Implemented more tolerant battery detection
I: 2219
2 changes: 2 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
**Bug fixes**

- 2360_, [macOS]: can't compile on macOS < 10.13. (patch by Ryan Schmidt)
- 2219_, [Linux] battery detection in `psutil.sensors_battery()` relies on an
assumption which is not true of all systems (patch by Sujal Singh).

5.9.8
=====
Expand Down
46 changes: 40 additions & 6 deletions psutil/_pslinux.py
Original file line number Diff line number Diff line change
Expand Up @@ -1542,17 +1542,45 @@ def multi_bcat(*paths):
return ret.strip()
return None

def detect_battery_path(*expected_files):
"""Find the device path having the maximum number of files
that are to be excepted for a battery. If no path has the
expected files, return None. Used as a fallback for when
the usual prefixes don't find a match.
"""
highest_score, final_battery = 0, None
for battery in os.listdir(POWER_SUPPLY_PATH):
battery_path = os.path.join(POWER_SUPPLY_PATH, battery)

actual_files = os.listdir(battery_path)
current_score = len([
f for f in actual_files if f in expected_files
])

if current_score > highest_score:
highest_score, final_battery = current_score, battery

return final_battery

bats = [
x
for x in os.listdir(POWER_SUPPLY_PATH)
if x.startswith('BAT') or 'battery' in x.lower()
]
if not bats:
return None
# Get the first available battery. Usually this is "BAT0", except
# some rare exceptions:
# https://github.com/giampaolo/psutil/issues/1238
root = os.path.join(POWER_SUPPLY_PATH, sorted(bats)[0])
if bats:
# Get the first available battery. Usually this is "BAT0", except
# some rare exceptions:
# https://github.com/giampaolo/psutil/issues/1238
root = os.path.join(POWER_SUPPLY_PATH, sorted(bats)[0])
else:
# Fallback to handle the rare exceptions
root = detect_battery_path(
"energy_now", "charge_now", "power_now", "current_now",
"energy_full", "charge_full", "capacity", "time_to_empty_now"
)

if root is None:
return

# Base metrics.
energy_now = multi_bcat(root + "/energy_now", root + "/charge_now")
Expand Down Expand Up @@ -1580,6 +1608,12 @@ def multi_bcat(*paths):
os.path.join(POWER_SUPPLY_PATH, "AC0/online"),
os.path.join(POWER_SUPPLY_PATH, "AC/online"),
)
if online is None:
# Fallback for when 'AC' and 'AC0' don't exist
online = multi_bcat(
detect_battery_path("online")
)

if online is not None:
power_plugged = online == 1
else:
Expand Down

0 comments on commit 93eeaa9

Please sign in to comment.