💾 Archived View for jean.ribes.ovh › rgb-mouse-as-a-battery-indicator captured on 2022-06-03 at 22:46:14. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2022-03-01)

-=-=-=-=-=-=-

I got a new gaming mouse, a logitech G203 LightSync.

This mouse has RBG LEDs, and is supported by libratbag [1] (also known as its frontend, Piper [2])

Sadly, for the time being, libratbag cannot control the RGB zones individually, nor enable the rainbow wave animation.

[1]

[2] Piper

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:

(MISSING)* slow-pulsing green for discharging

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 !