Automatic Power Profile Switching on AC/Battery

Problem

I wanted my laptop to automatically switch between power profiles when plugging/unplugging the AC adapter. The default behavior either doesn’t exist or requires manual intervention every time (and let’s be honest, I will forget).

Solution

A simple Ruby script triggered by udev rules that detects AC power state and switches TuneD profiles accordingly.

The Ruby Script

Save as /usr/local/bin/power-profile-switch.rb:

#!/usr/bin/env ruby

# Check if on AC power by reading the online status
ac_online = false

# Find AC adapter(s) and check if any are online
Dir.glob('/sys/class/power_supply/AC*/online').each do |path|
  if File.read(path).strip == '1'
    ac_online = true
    break
  end
end

# Using TuneD
if ac_online
  system('tuned-adm', 'profile', 'throughput-performance')
else
  system('tuned-adm', 'profile', 'powersave')
end

The udev Rule

Save as /etc/udev/rules.d/99-power-profile.rules:

# Trigger on AC adapter state changes
SUBSYSTEM=="power_supply", ATTR{online}=="0", RUN+="/usr/local/bin/power-profile-switch.rb"
SUBSYSTEM=="power_supply", ATTR{online}=="1", RUN+="/usr/local/bin/power-profile-switch.rb"

Boot-time Profile Setting

There’s one gap: if you shut down in one state and boot up in another state, the power profile won’t match the current power state until you plug/unplug the adapter. A systemd timer solves this by checking the power state at boot.

systemd Service File

Save as /etc/systemd/system/power-profile-switch.service:

[Unit]
Description=Set power profile based on AC adapter status
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/power-profile-switch.rb
User=root

systemd Timer File

Save as /etc/systemd/system/power-profile-switch.timer:

[Unit]
Description=Run power profile switch at boot
Requires=power-profile-switch.service

[Timer]
OnBootSec=30sec

[Install]
WantedBy=timers.target

Installation

# Make the script executable
sudo chmod +x /usr/local/bin/power-profile-switch.rb

# Set correct SELinux context (if SELinux is enabled)
sudo restorecon -v /usr/local/bin/power-profile-switch.rb

# Reload udev rules
sudo udevadm control --reload-rules

# Enable and start the systemd timer
sudo systemctl enable power-profile-switch.timer
sudo systemctl start power-profile-switch.timer

How It Works

The udev rule triggers whenever the online attribute of any power supply changes (i.e., when you plug or unplug the AC adapter). The Ruby script then checks all AC adapters and switches to:

The timer runs once, 30 seconds after boot, allowing time for power supply detection. This preserves your ability to manually change power profiles without the system constantly overriding your choices.

Created: 2025-10-24 -- Updated: 2025-10-28