Skip to content

Conversation

@brutalsam96
Copy link

Summary

Refactored the omarchy-battery-monitor script to improve reliability of battery notifications.

Changes

Rewrote battery level fetching and parsing logic, removing dependency on omarchy-battery-remaining call that may have caused inconsistent notifications mentioned in issue #3066

Updated notification flow to use two levels:

A higher-threshold warning.

A lower-threshold critical alert.

Outcome

Should ensure battery notifications trigger consistently and notify twice now.

P.S If omarchy-battery-remaining script is not used elsewhere it should be obselete and safe to remove.

…ations, slightly altered parsing logic which should fix inconsistent notification issues, omarchy-battery-remaining script is now implemented inside this script rendering it obsolete unless it is used by some other scripts
@scale03
Copy link
Contributor

scale03 commented Dec 9, 2025

Hi! 👋
the dual-threshold logic (Warning vs Critical), it's a great UX improvement. I've been profiling this service casually with eBPF tracing tools, and I noticed that the current implementation produce significant overhead and context switch just to notify the battery level warning. Because the script spawns external binaries (upower, grep, awk, find, head) multiple times per cycle, it creates noticeable PID churn and syscall latency every 30 seconds.

I'm also seeing a lot of ENOENT noise in the systemd journal because of race conditions when he try tracking these short-lived processes.

🔍 Click to see the trace log evidence (ENOENT storm)

trace > omarchy-battery.log

Proposal: We can achieve the exact same logic with near-zero overhead (<1ms execution) by reading directly from the kernel interface (/sys/class/power_supply/) using pure Bash built-ins, instead of shelling out to upower.

@brutalsam96
Copy link
Author

Hi! 👋 the dual-threshold logic (Warning vs Critical), it's a great UX improvement. I've been profiling this service casually with eBPF tracing tools, and I noticed that the current implementation produce significant overhead and context switch just to notify the battery level warning. Because the script spawns external binaries (upower, grep, awk, find, head) multiple times per cycle, it creates noticeable PID churn and syscall latency every 30 seconds.

I'm also seeing a lot of ENOENT noise in the systemd journal because of race conditions when he try tracking these short-lived processes.

🔍 Click to see the trace log evidence (ENOENT storm)
trace > omarchy-battery.log

Proposal: We can achieve the exact same logic with near-zero overhead (<1ms execution) by reading directly from the kernel interface (/sys/class/power_supply/) using pure Bash built-ins, instead of shelling out to upower.

Hello there, yes i have been thinking on reading directly from kernel but i choose not to stray too far from the original script just to whip up something fast and test while my battery was discharging to find out why exactly it was working inconsistently(which i couldn't exactly tell why), but i guess you are right it can be a lot cleaner and free of overhead, i might look into it later but you are free to contribute upon this pr i have sent you a collaboration request to my fork.

@scale03
Copy link
Contributor

scale03 commented Dec 10, 2025

Hi @brutalsam96 — thanks for the invite!

On second thought, instead of bundling the refactor here, I think it's safer to just fix the fullscreen notification issue (#3066) first while maintaining the current logic.

Actually the problem is not the bash script alone ( notify-send -u critical) this flag is already there but cannot force the visual layer. It can only request "critical" status; the config file decides where "critical" things get drawn. Without the config change, the script fix is useless for fullscreen scenarios.

Im testing out if this could be the final fix for the issue you mentioned, maybe i will make a separate pr for this one, but i would like to collaborate for a refactor later as well, in orther to use sysfs if upower is not prefered istead for this use case. But im not sure is gonna be accepted (i already tried it locally and works fine on my thinkpad)

@brutalsam96
Copy link
Author

@scale03 no problem, i have found that we have status and capacity at the /sys/class/power_supply, this is much easier than parsing full info from upower, but now need to dive deeper and if all drivers provide same status and capacity files also the path /sys/class/power_supply/BAT0, need to also find out if BAT0 is always the name for the battery and maybe handle multiple battery sources.

@scale03
Copy link
Contributor

scale03 commented Dec 10, 2025

@brutalsam96 Nice, i just created a pr to fix the silent death while on full screen. #3838 completely agree on dropping the upower parsing for direct sysfs reads could be a huge win in the log run.

Since BAT0 isn't universal (and some machines have multiple batteries like BAT0 + BAT1), we probably shouldn't hardcode the path.

I suggest we iterate through /sys/class/power_supply/* and check the type file to confirm it's a "Battery" before reading status and capacity. That way we support multi-battery setups and different driver naming conventions out of the box.

@brutalsam96
Copy link
Author

@scale03
Solid work on finding and fixing disappearing notifications.
Exactly my thoughts, assuming BAT as a sole source of information can lead to problems with machines with multiple batteries or desktops with UPS might also be recognized this way.
Luckily for that upower comes in handy because it combines and calculates in such cases so even initial script that targeted bat was off the mark, so correct way to run DisplayDevice through the upower -i and parse that information

~ ❯ upower -e
/org/freedesktop/UPower/devices/battery_BAT0
/org/freedesktop/UPower/devices/line_power_AC0
/org/freedesktop/UPower/devices/DisplayDevice

Then again this shouldn't do much with overhead and context switch problems, i will research more regarding this matter, until then i will push updated commit that utilizes DisplayDevice instead of BAT.
@dhh @ryanrhughes would love to hear your thoughts regarding this problem as well.

@scale03
Copy link
Contributor

scale03 commented Dec 11, 2025

I'm not saying that this is a problem, I'm just saying that for this monitor battery script and maybe something else too the logic is simple enough that could be refactored in bash only. I notice also that systemd is producing every 30 second A LOT of enoet while monitoring the battery monitor script's childs but is just noise not a problem, and the fact that runs every 30 sec to check the battery life could make sense to optimize it (is good for the battery itself) but probably upower is still necessary somehow so maybe is better open a discussion to discuss about this instead of commenting this pr.

Cheers

Copy link
Collaborator

@ryanrhughes ryanrhughes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some feedback for a few small changes. I've only validated this on my laptop but to others' points; do not know what this might do in a situation where you have a UPS or something on a desktop. However, in those cases, perhaps you'd also want the same notice.

…ining to use more concise logic to extract remaining percentage digits and simplified most of the script as suggested
@brutalsam96
Copy link
Author

Added requested changes.
Aside from this i was working on different solution than 30 second timer and service that runs script each time.
Basically we got UPower Dbus service that send SIGNAL on PropertiesChange event, meaning it sends battery info each time it's properties change usually when you lose a percentage of battery charge, i am working on a python script that should be able to listen in on Dbus System Sessions and work out battery monitoring logic using dbus-next python library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants