Ubuntu: Run command when idle/active



Question:

I need to run custom comand when:

  1. Computer is idle for X minutes (no key pressed)
  2. Key pressed

What I want o achieve actually is power saving feature for my keyboard.

I want to use:

g413-led -a 000000  g413-led -a FFFFFF  

To turn on/off keyboard backlight using https://github.com/MatMoul/g810-led.

The first is fairly easy using one of:

  • xidle
  • xprintidle
  • xautolock

Please advice if there are better, more optimal ways?

But what about lighing it up again on keypress or resume from idle? I guess running command on each keypress is overkill. Is there event for power saving options? How does display power saving works?

enter image description here

Can I reuse same events/timeout?


Solution:1

The solution I came up with is DBUS events.

I first run dbus-monitor to see what events will trigger when monitor goes/wakes from sleep:

signal time=1515274499.244468 sender=org.freedesktop.DBus -> destination=:1.394 serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired  string ":1.394"  signal time=1515274499.244502 sender=org.freedesktop.DBus -> destination=:1.394 serial=4 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameLost  string ":1.394"  signal time=1515274559.337480 sender=:1.6 -> destination=:1.2 serial=29015 path=/org/gnome/Mutter/IdleMonitor/Core; interface=org.gnome.Mutter.IdleMonitor; member=WatchFired  uint32 440  signal time=1515274559.337878 sender=:1.2 -> destination=(null destination) serial=3288 path=/org/gnome/SessionManager/Presence; interface=org.gnome.SessionManager.Presence; member=StatusChanged  uint32 3  signal time=1515274559.338267 sender=:1.2 -> destination=(null destination) serial=3290 path=/org/gnome/SessionManager/Presence; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged  string "org.gnome.SessionManager.Presence"  array [  dict entry(  string "status"  variant uint32 3  )  ]  array [  ]  signal time=1515274569.389778 sender=:1.6 -> destination=(null destination) serial=29018 path=/org/gnome/Shell; interface=org.gnome.Shell.Extensions; member=ExtensionStatusChanged  string "auto-move-windows@gnome-shell-extensions.gcampax.github.com"  int32 2  string ""  signal time=1515274569.398929 sender=:1.6 -> destination=(null destination) serial=29019 path=/org/gnome/Shell; interface=org.gnome.Shell.Extensions; member=ExtensionStatusChanged  string "clipboard-indicator@tudmotu.com"  int32 2  string ""  signal time=1515274569.399633 sender=org.freedesktop.DBus -> destination=:1.6 serial=5195 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameLost  string "org.kde.StatusNotifierWatcher"  signal time=1515274569.399660 sender=org.freedesktop.DBus -> destination=(null destination) serial=850 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged  string "org.kde.StatusNotifierWatcher"  string ":1.6"  string ""  signal time=1515274569.404274 sender=:1.6 -> destination=(null destination) serial=29022 path=/org/gnome/Shell; interface=org.gnome.Shell.Extensions; member=ExtensionStatusChanged  string "ubuntu-appindicators@ubuntu.com"  int32 2  string ""  signal time=1515274569.442137 sender=:1.6 -> destination=(null destination) serial=29025 path=/org/gnome/Shell; interface=org.gnome.Shell.Extensions; member=ExtensionStatusChanged  string "ubuntu-dock@ubuntu.com"  int32 2  string ""  signal time=1515274569.455035 sender=:1.6 -> destination=(null destination) serial=29027 path=/org/gnome/ScreenSaver; interface=org.gnome.ScreenSaver; member=ActiveChanged  boolean true  signal time=1515274569.657300 sender=:1.6 -> destination=:1.42 serial=29037 path=/org/gnome/Mutter/IdleMonitor/Core; interface=org.gnome.Mutter.IdleMonitor; member=WatchFired  uint32 491  signal time=1515274569.657404 sender=:1.6 -> destination=(null destination) serial=29038 path=/org/gnome/Mutter/DisplayConfig; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged  string "org.gnome.Mutter.DisplayConfig"  array [  dict entry(  string "PowerSaveMode"  variant int32 3  )  ]  array [  ]  signal time=1515276608.243100 sender=:1.6 -> destination=:1.2 serial=29039 path=/org/gnome/Mutter/IdleMonitor/Core; interface=org.gnome.Mutter.IdleMonitor; member=WatchFired  uint32 489  signal time=1515276608.243573 sender=:1.2 -> destination=(null destination) serial=3291 path=/org/gnome/SessionManager/Presence; interface=org.gnome.SessionManager.Presence; member=StatusChanged  uint32 0  signal time=1515276608.243843 sender=:1.2 -> destination=(null destination) serial=3292 path=/org/gnome/SessionManager/Presence; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged  string "org.gnome.SessionManager.Presence"  array [  dict entry(  string "status"  variant uint32 0  )  ]  array [  ]  signal time=1515276608.244032 sender=:1.6 -> destination=:1.42 serial=29040 path=/org/gnome/Mutter/IdleMonitor/Core; interface=org.gnome.Mutter.IdleMonitor; member=WatchFired  uint32 494  signal time=1515276608.270459 sender=:1.6 -> destination=(null destination) serial=29042 path=/org/gnome/Mutter/DisplayConfig; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged  string "org.gnome.Mutter.DisplayConfig"  array [  dict entry(  string "PowerSaveMode"  variant int32 0  )  ]  array [  ]  signal time=1515276623.523917 sender=:1.6 -> destination=:1.42 serial=29043 path=/org/gnome/Mutter/IdleMonitor/Core; interface=org.gnome.Mutter.IdleMonitor; member=WatchFired  uint32 491  signal time=1515276623.554451 sender=:1.6 -> destination=(null destination) serial=29047 path=/org/gnome/Mutter/DisplayConfig; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged  string "org.gnome.Mutter.DisplayConfig"  array [  dict entry(  string "PowerSaveMode"  variant int32 3  )  ]  array [  ]  signal time=1515276668.529836 sender=:1.6 -> destination=:1.2 serial=29048 path=/org/gnome/Mutter/IdleMonitor/Core; interface=org.gnome.Mutter.IdleMonitor; member=WatchFired  uint32 440  signal time=1515276668.530236 sender=:1.2 -> destination=(null destination) serial=3293 path=/org/gnome/SessionManager/Presence; interface=org.gnome.SessionManager.Presence; member=StatusChanged  uint32 3  signal time=1515276668.530565 sender=:1.2 -> destination=(null destination) serial=3295 path=/org/gnome/SessionManager/Presence; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged  string "org.gnome.SessionManager.Presence"  array [  dict entry(  string "status"  variant uint32 3  )  ]  array [  ]  signal time=1515279067.394398 sender=:1.6 -> destination=:1.2 serial=29051 path=/org/gnome/Mutter/IdleMonitor/Core; interface=org.gnome.Mutter.IdleMonitor; member=WatchFired  uint32 498  signal time=1515279067.394982 sender=:1.2 -> destination=(null destination) serial=3296 path=/org/gnome/SessionManager/Presence; interface=org.gnome.SessionManager.Presence; member=StatusChanged  uint32 0  signal time=1515279067.395139 sender=:1.2 -> destination=(null destination) serial=3297 path=/org/gnome/SessionManager/Presence; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged  string "org.gnome.SessionManager.Presence"  array [  dict entry(  string "status"  variant uint32 0  )  ]  array [  ]  signal time=1515279067.395662 sender=:1.6 -> destination=:1.42 serial=29052 path=/org/gnome/Mutter/IdleMonitor/Core; interface=org.gnome.Mutter.IdleMonitor; member=WatchFired  uint32 496  signal time=1515279067.414904 sender=:1.6 -> destination=(null destination) serial=29054 path=/org/gnome/Mutter/DisplayConfig; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged  string "org.gnome.Mutter.DisplayConfig"  array [  dict entry(  string "PowerSaveMode"  variant int32 0  )  ]  array [  ]  signal time=1515279076.828255 sender=:1.6 -> destination=(null destination) serial=29063 path=/org/gnome/Shell; interface=org.gnome.Shell.Extensions; member=ExtensionStatusChanged  string "ubuntu-dock@ubuntu.com"  int32 1  string ""  signal time=1515279076.829775 sender=org.freedesktop.DBus -> destination=(null destination) serial=851 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged  string "org.kde.StatusNotifierWatcher"  string ""  string ":1.6"  signal time=1515279076.829812 sender=org.freedesktop.DBus -> destination=:1.6 serial=5215 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired  string "org.kde.StatusNotifierWatcher"  signal time=1515279076.829824 sender=:1.6 -> destination=(null destination) serial=29066 path=/org/gnome/Shell; interface=org.gnome.Shell.Extensions; member=ExtensionStatusChanged  string "ubuntu-appindicators@ubuntu.com"  int32 1  string ""  signal time=1515279076.841923 sender=:1.6 -> destination=(null destination) serial=29067 path=/org/gnome/Shell; interface=org.gnome.Shell.Extensions; member=ExtensionStatusChanged  string "clipboard-indicator@tudmotu.com"  int32 1  string ""  signal time=1515279076.844396 sender=:1.6 -> destination=(null destination) serial=29068 path=/org/gnome/Shell; interface=org.gnome.Shell.Extensions; member=ExtensionStatusChanged  string "auto-move-windows@gnome-shell-extensions.gcampax.github.com"  int32 1  string ""  signal time=1515279076.851323 sender=:1.6 -> destination=(null destination) serial=29069 path=/org/gnome/ScreenSaver; interface=org.gnome.ScreenSaver; member=ActiveChanged  boolean false  signal time=1515279076.896958 sender=:1.6 -> destination=(null destination) serial=29218 path=/StatusNotifierWatcher; interface=org.kde.StatusNotifierWatcher; member=StatusNotifierItemRegistered  string "/"  signal time=1515279076.921110 sender=:1.38 -> destination=(null destination) serial=2735 path=/org/gnome/evolution/dataserver/CalendarView/1887/93; interface=org.gnome.evolution.dataserver.CalendarView; member=complete  array [  string ""  string ""  ]  signal time=1515279076.924727 sender=:1.34 -> destination=(null destination) serial=2701 path=/org/gnome/evolution/dataserver/CalendarView/1870/92; interface=org.gnome.evolution.dataserver.CalendarView; member=complete  array [  string ""  string ""  ]  signal time=1515279077.686970 sender=:1.6 -> destination=(null destination) serial=30014 path=/StatusNotifierWatcher; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged  string "org.kde.StatusNotifierWatcher"  array [  dict entry(  string "RegisteredStatusNotifierItems"  variant array [  string ":1.66/org/ayatana/NotificationItem/software_update_available"  ]  )  ]  array [  

I first tried to go for org.gnome.Mutter.IdleMonitor, but uint32 values were constantly incrementing, not sure why?

I settled with StatusChanged, here is the final script:

#!/bin/bash  # Turn keyboard backlight on/off using https://github.com/MatMoul/g810-led    g413-led -a FFFFFF # always turn on on startup (it turns off for some reason on reboot)    dbus-monitor --session "type=signal,interface=org.gnome.SessionManager.Presence,member=StatusChanged" |    while read x; do        case "$x" in          *"uint32 3"*) g413-led -a 000000;;          *"uint32 0"*) g413-led -a FFFFFF;;        esac    done  

Screensaver events can also work:

g413-led -a FFFFFF # always turn on on startup (it turns off for some reason on reboot)    dbus-monitor --session "type='signal',interface='org.gnome.ScreenSaver'" |    while read x; do        case "$x" in          *"boolean true"*) g413-led -a 000000;;          *"boolean false"*) g413-led -a FFFFFF;;        esac    done  

Of course, you can put any command you wish. The advantage of the first script comparing to this one is that it lights up keyboard before user login which makes it easier to type password.

The only downside is that keyboards lights up after user login, not on keypress, but I can live with that.

I was experimenting with:

dbus-monitor --session "type='signal',interface='org.freedesktop.DBus.Properties',path='/org/gnome/Mutter/DisplayConfig'" | grep 'variant int32' |    while read x; do        case "$x" in          *"variant int32 3"*) g413-led -a 000000;;          *"variant int32 0"*) g413-led -a FFFFFF;;        esac    done  

but it didn't work for some reason, probably grep issue.


Solution:2

Tiny background process

Your setup seems quite a complicated one for a simple issue. What I would do is simply run a tiny backround process, checking idle time once per 2 seconds or so, take one action if idle time exceeds the limit, another action if it switches to below set idle time.

The script:

#!/usr/bin/env python3  import time  import subprocess    # set idle time (seconds)  t = 60    # set commands  on_idle = ["g413", "-led", "-a", "000000"]  on_active = ["g413", "-led", "-a", "FFFFFF"]    def set_state(cmd):      subprocess.Popen(cmd)    def get_idle():      return int(subprocess.check_output("xprintidle").decode("utf-8").strip())/1000    idle1 = 0    while True:      time.sleep(2)      idle2 = get_idle()      # if idle time exceeds (passes) the limit, run one command      if all([idle2 >= t, idle1 < t]):          set_state(on_idle)      # if idle time switches to below (passes) the limit, run another command      elif all([idle2 <= t, idle1 > t]):          set_state(on_active)      idle1 = idle2  

To use

  • Make sure xprintidle is installed

    sudo apt install xprintidle  
  • Copy the script into an empty file, save it as switch_light.py

  • Set the desired idle time to take action after:

    # set idle time (seconds)  t = 60  
  • Run it by the command:

    python3 /path/to/switch_light.py  
  • If all works fine, add it to Startup Applications.

Note(s)

  • Couldn't test it since I don't have your keyboard, but tested with other commands, it does the job nicely.

  • You can use the script with any other command:

    # set commands  on_idle = ["g413", "-led", "-a", "000000"]  on_active = ["g413", "-led", "-a", "FFFFFF"]  

    Just make sure you separate arguments like in the example.

  • If you only want an action on exceeding idle time (or the other way around), just comment out:

    # if idle time switches to below (passes) the limit, run another   elif all([idle2 <= t, idle1 > t]):      set_state(on_active)  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »