I got a new gaming mouse, a logitech G203 LightSync.
This mouse has RBG LEDs, and is supported by libratbag (also known as its frontend, Piper)
Sadly, for the time being, libratbag cannot control the RGB zones individually, nor enable the rainbow wave animation.
it's very cool and pretty, but not very useful
On Windows, the G Hub software enables some integrations with games. But when you play a game, your hand is on the mouse, so you cannot see the LEDs !
Libratbag provides an Python API as well as a command-line interface, so I can program whatever color, animation (pulse, solid) and brightness I want.
Battery indicator
I decided to use the RGB LEDs as a battery indicator:
- fast-pulsing red for
> 99%
and<10%
battery - fast-pulsing orange for
<30%
- slow-pulsing green for discharging
- slow-pulsing blue for charging
I can get the battery status through the psutil
Python package.
Notification indicator
I also added another feature: a fast-pulsing bright white whenever a notification comes up.
The D-Bus API allows you to not only listen for incoming notifications, but also to listen for the dismissal event. So the notification indicator won't be a dumb timer, but will correctly react to the desktop state.
I didn't implement a timeout for the notification indicator, because my GNOME desktop automatically dimisses notifications (they remain in the notification history).
code
#!/usr/bin/env python3
from psutil import sensors_battery
from piper.ratbagd import Ratbagd, RatbagdLed
from time import sleep
import dbus
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GLib
from threading import Thread
STATE_ALARM = 'alarme'
STATE_OK = 'ok'
STATE_CHARGING = 'charging'
STATE_UNPLUG = 'unplug'
STATE_NOTIF = 'notif'
color_ok = (115, 210, 22)
color_alarme = (255, 95, 0)
color_unplug = (255, 0, 0)
color_charge = (128, 255, 255)
color_notif = (255, 255, 255)
timing_alarme = 500
timing_ok = 3000
timing_charge = 2000
def set_rgb(color, duration, brightness=200):
r = Ratbagd(api_version=1)
souris = r.devices[0]
profil = souris.profiles[0]
led = profil.leds[0]
led.mode = RatbagdLed.Mode.BREATHING
led.color = color
led.brightness = brightness
led.effect_duration = duration
souris.commit()
def apply_state(state):
if state == STATE_OK:
set_rgb(color_ok, timing_ok)
elif state == STATE_ALARM:
set_rgb(color_alarme, timing_alarme)
elif state == STATE_CHARGING:
set_rgb(color_charge, timing_charge)
elif state == STATE_UNPLUG:
set_rgb(color_unplug, timing_alarme)
elif state == STATE_NOTIF:
set_rgb(color_notif, timing_alarme)
notif = False
def handler(bus, msg):
print(msg)
member = msg.get_member()
print(member)
global notif
if member == 'Notify':
notif = True
elif member == 'NotificationClosed':
notif = False
return
session_bus = dbus.SessionBus(mainloop=DBusGMainLoop(set_as_default=True))
loop = GLib.MainLoop()
session_bus.add_match_string("interface='org.freedesktop.Notifications',eavesdrop='true'")
session_bus.add_message_filter(handler)
Thread(target=loop.run, daemon=True).start()
saved_state = 'err'
state = 'err'
if __name__ == '__main__':
while True:
bat = sensors_battery()
if bat.percent < 30:
new_state = STATE_ALARM
if bat.percent >= 30:
new_state = STATE_OK
if bat.percent < 10:
new_state = STATE_UNPLUG
if bat.power_plugged:
if bat.percent >= 99:
new_state = STATE_UNPLUG
else:
new_state = STATE_CHARGING
if notif:
new_state = STATE_NOTIF
notif = False
if new_state != state:
print(new_state)
state = new_state
apply_state(state)
saved_state = state
sleep(0.5)
Conclusion & disclaimers
This script has only been tested on Ubuntu 20.04 LTS, with the Ubuntu GNOME desktop, and with my Logitech G203 LightSync.
If you have RGB mouse that has multiple LEDs, this script will only use the first one. You can modify the function set_rgb
to use multiple LEDs.
You could even use each LED for a separate indicator, the possibilities are endless !