10

How can I get an on-screen notification using notify-osd when I plug/unplug the charger?

Seth
  • 59,332
kernel_panic
  • 12,102

3 Answers3

8

Switching between AC power and battery power should generate an event on the D-Bus system bus. Run dbus-monitor --system and watch what events are generated on your system.

If you have upower running, you get more specialized notifications from upower -m.

#!/bin/sh
upower -m |
while read -r _time _2 _3 device; do
  [ "$device" = "/org/freedesktop/UPower/devices/line_power_AC" ] || continue
  notify-send "$(acpi -a)"
done

You can also get events from acpi_listen.

#!/bin/sh
acpi_listen |
while read -r what junk; do
  [ "$what" = "ac_adapter" ] || continue
  notify-send "$(acpi -a)"
done

Run this script when you want to start seeing notifications, or add it to your session startup.

Seth
  • 59,332
7

enter image description here enter image description here

dbus

Some people reported my earlier udev solution sent the notification too many times when the power cable was plugged in. I couldn't reproduce that but I wrote this python script to utilize dbus instead of udev. Save it as a .py file somewhere on your hard drive. Mark the file executable by running:

sudo chmod +x yourFile.py  

and add it to your startup applications as described here. This script requires the package acpi be installed.

#!/usr/bin/python

import dbus
from dbus.mainloop.glib import DBusGMainLoop
import gobject
import subprocess


dbus_loop = DBusGMainLoop()
bus = dbus.SystemBus(mainloop=dbus_loop)

onMessage="Power plugged in!"
offMessage="Power unplugged!"
onImage="/usr/share/icons/gnome/32x32/devices/ac-adapter.png"
offImage="/usr/share/icons/gnome/32x32/status/battery-full.png"

def callback():
    state = subprocess.check_output(["acpi", "-a"]).split(':')[1].strip()
    if state == "on-line":
        subprocess.call(["notify-send", "-i", onImage, onMessage])
    elif state == "off-line":
        subprocess.call(["notify-send", "-i", offImage, offMessage])

bus.add_signal_receiver(callback, 'Changed', 'org.freedesktop.UPower.Device', 'org.freedesktop.UPower', '/org/freedesktop/UPower/devices/line_power_AC')

loop = gobject.MainLoop()
loop.run()

udev

With a little experimentation (and a little help) I was able to utilize a udev rule to accomplish this. Some people have reported that it sometimes sends the notification more than once but I have not had any problems. YMMV.

Create a script with the following contents:

#!/bin/bash

# Set this to your username
USER="some_user"

if [ "$POWER" == "on" ]
  then
  DISPLAY=:0 /bin/su $USER -c '/usr/bin/notify-send -i /usr/share/icons/gnome/32x32/devices/ac-adapter.png "Power cable plugged in."'
elif [ "$POWER" == "off" ]
  then
  DISPLAY=:0 /bin/su $USER -c '/usr/bin/notify-send -i /usr/share/icons/gnome/32x32/status/battery-full.png "Power cable unplugged."'
fi

replacing some_user with your username. Mark the file executable by running:

sudo chmod +x /path/to/script.sh  

replacing /path/to/script.sh with the path to where you saved the script.

Next create a file in /etc/udev/rules.d named 10-power.rules with the contents:

SUBSYSTEM=="power_supply", ACTION=="change", ENV{POWER_SUPPLY_ONLINE}=="0", OPTIONS+="last_rule", RUN+="/path/to/script.sh" ENV{POWER}="off"
SUBSYSTEM=="power_supply", ACTION=="change", ENV{POWER_SUPPLY_ONLINE}=="1", OPTIONS+="last_rule", RUN+="/path/to/script.sh" ENV{POWER}="on"

again replacing /path/to/script.sh with the path to the script you created earlier.

Now reload the udev rules by running:

sudo udevadm control --reload-rules                              

Unplug the power cable. You should get a notification.

Seth
  • 59,332
2

Script Source

#!/usr/bin/env bash
#
###########################################################
# Author: Serg Kolo , contact: 1047481448@qq.com 
# Date: March 11, 2016
# Purpose: Script to detect connection/disconnection
#          of the ac adapter
#          
# 
# Written for: http://askubuntu.com/q/542986/295286
# Tested on: Ubuntu 14.04 LTS
# Version: 0.2
###########################################################
# Copyright: Serg Kolo , 2016
#    
#     Permission to use, copy, modify, and distribute this software is hereby granted
#     without fee, provided that  the copyright notice above and this permission statement
#     appear in all copies.
#
#     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
#     THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
#     DEALINGS IN THE SOFTWARE.
#set -x
ARGV0="$0"
ARGC=$#

test_presence()
{
  on_ac_power
  echo $?
}

notify_change()
{
   pgrep -f '/usr/bin/X' > /dev/null && GUI=true
   connected='AC adapter connected'
   disconnected='AC adapter disconnected'

   if [ $1 -eq 0 ]
   then
           wall <<< $connected        
           $GUI && DISPLAY=:0 notify-send 'AC adapter connected'

   else
           wall <<< $connected
           $GUI && DISPLAY=:0 notify-send 'AC adapter disconnected'
   fi
}

main()
{
  FLAG=$(test_presence)

  while true
  do
     STATUS=$(test_presence)

     if [ $STATUS -eq $FLAG   ]
     then
        continue
     else
        notify_change $STATUS
        FLAG=$STATUS
     fi

  sleep 3 #0.25
  done
}  

main 

Getting the script

The script is also added to my github ; that version will be updated and developed a tiny bit more.

You can get it by doing the following:

  1. sugo apt-get install git
  2. cd /opt

  3. git clone https://github.com/SergKolo/sergrep.git

The script will be in /opt/sergrep directory, named notify_ac_change.sh

Concept/Design

The key questions are "How do we check presence of the AC adapter ?" and "How do we detect changes?"

Well, this issue has been solved long ago by other developers. Ubuntu comes by default with a script called on_ac_power, which is stored in /usr/bin/on_ac_power. Power adapter can be mentioned under different subsystems in the kernel ( ACPI or APM ) , but this script makes our job simpler - authors have covered a lot of possible variations. It return only exit status so it's appropriate for use in if statements.

Why is on_ac_power is good choice ? Because it relies on checking multiple subsystems. It also provides simple enough command to work with - the result is either true or false.

Thus we have presence detecting tool, but what about logic ? We need to poll the presence and detect change in the state. What we can do is to store exit status of on_ac_power and continuously compare current state with what we have saved, once it changes - send notification, save the status again, and keep comparing again,looping. Basic idea is the use of flags.

In short, we initialize a snapshot of the state, and then continuously poll for change from the snapshot; once change occurs - notify and reset snapshot.