read

I use a Logitech Performance MX wireless mouse, on Ubuntu 18.10 (Cosmic Cuttlefish), with Gnome 3.30.2 Ubuntu 20.04, with Gnome 3.36.2.

This mouse uses regular 1.2V AA NiMH rechargeable battery1, which usually lasts 3 months on a single charge

The problem is that Ubuntu's power system tries to detect how much voltage is left, and either the voltage sensors or the calculation algorithm is completely broken, so it starts to show notifications 6-8 weeks before it really runs out.

The worse part is that these notifications won't fade away after a few seconds like you'd expect. And to make it more infuriating, they have an audible alert, and show up after a every period of brief inactivity, which means you'll get dozens of notifications per day -- and you'll will need to click to dismiss them every single time.

I don't really need to be notified two months in advance on a mouse battery (or at all). When it runs out, I can just connect the cable. It's not like a printer, that you need to buy ink in advance.

It seems I'm not alone: tons of users have reported the same problem for years (1, or 2, or 3), but no solution.

It seems that upower developers recognize that the battery % should be ignored, but still emits warnings on low battery, and Gnome Settings Daemon doesn't offer any way to selectively disable or control these notifications:

$ upower --dump
Device: /org/freedesktop/UPower/devices/mouse_hidpp_battery_12  
  native-path:          hidpp_battery_12
  model:                Performance MX
  serial:               104a-8a-10-ee-9b
  power supply:         no
  updated:              Sun Jun  2 18:09:54 2019 (15 seconds ago)
  has history:          yes
  has statistics:       yes
  mouse
    present:             yes
    rechargeable:        yes
    state:               discharging
    warning-level:       none
    battery-level:       critical
    percentage:          5% (should be ignored) ◀◀◀
    icon-name:          'battery-caution-symbolic'

Most of the workarounds I found involve patching gnome-settings-daemon (which I've done before, but for different reasons), or disabling power notifications entirely. I dislike both solutions, and wanted to selectively disable only mouse battery notifications, without touching anything else.

Thanks to a tip by @daFritz84, I decided to patch upowerd directly (although I used a different method than Stefan). The good news is that upower has few dependencies, so it's pretty straightforward to compile and patch your system.

Here's the patch to be applied over up-device.c:

--- up-device.c    2019-06-15 00:18:57.607554731 -0400
+++ up-device-silent.c    2019-06-15 00:19:03.207705276 -0400
@@ -63,6 +63,15 @@
     UpDeviceLevel warning_level, battery_level;
     UpExportedDevice *skeleton = UP_EXPORTED_DEVICE (device);

+    /* Disable warning notifications for wireless mice with rechargeable batteries */
+    int type = up_exported_device_get_type_ (skeleton);
+    int state = up_exported_device_get_state(skeleton);
+    if (type == UP_DEVICE_KIND_MOUSE && state == UP_DEVICE_STATE_DISCHARGING) {
+        warning_level = UP_DEVICE_LEVEL_NONE;
+        up_exported_device_set_warning_level (skeleton, warning_level);
+        return;
+    }
+
     /* Not finished setting up the object? */
     if (device->priv->daemon == NULL)
         return;

(Update 2021-07: the latest upower 0.99.12 changed structured slightly, so you need to use the updated patch)

Here's the step-by-step, tested on Ubuntu 18.04, 20.04, 20.10, 21.04, and Manjaro (disclaimer: provided as is; you are responsible for checking the accuracy of the patch and ensure it won't ruin your system. Having said that, let me know in the comments below if it doesn't work for you, and I'll try to incorporate new distributions over time):

#!/bin/bash
set -e

# See https://wrgms.com/disable-mouse-battery-low-spam-notification/
# for instructions on how to use it
#
# TL;DR: run with "--keyboard" if you want to patch upower to ignore both
# mice and keyboard notifications (by default it ignores only mice)

# Check distro and upower version in use, and install required libraries
#
echo  
echo "------------------------------"  
upower --version  
echo "------------------------------"  
echo

UPOWER_ORIG_VER=`upower --version`  
OS=`awk -F= '/^ID=/{print $2}' /etc/os-release`  
OS_VER=`awk -F= '/^VERSION_ID=/{print $2}' /etc/os-release | cut -d "\"" -f 2`  
OS_VER_MAJOR=`echo ${OS_VER} | awk -F. '{print $1}'`

PATCH_LEGACY_URL="https://gist.githubusercontent.com/guiambros/f2bf07f1cc085f8f0b0a9e04c0a767b4/raw/73efac967c8fc9539802e7aa8eeba5492f8ae3b1/up-device-legacy.patch"  
PATCH_CURRENT_URL="https://gist.githubusercontent.com/guiambros/f2bf07f1cc085f8f0b0a9e04c0a767b4/raw/73efac967c8fc9539802e7aa8eeba5492f8ae3b1/up-device-current-0.99.12p.patch"  
PATCH_NAME="up-device.patch"  
PATCH_URL=${PATCH_CURRENT_URL}

if [ "$OS" == "manjaro" ]  
then  
    echo "-- Manjaro detected; installing required libraries"
    sudo pacman -S base-devel gtk-doc gobject-introspection git
    PATH_UPOWERD="/usr/lib"
    PATH_UPOWER="/usr/bin"

elif [ "$OS" == "ubuntu" ]  
then  
    echo "-- Ubuntu detected; installing required libraries"
    sudo apt install -y git gtk-doc-tools gobject-introspection libgudev-1.0-dev libusb-1.0-0-dev autoconf libtool autopoint
    PATH_UPOWER="/usr/bin"

    if [ "${OS_VER}" == "20.10" ]
    then
        echo "--- Ubuntu version 20.10 (Groovy Gorilla) detected"
        PATH_UPOWERD="/usr/libexec"
        UPOWER_BRANCH="UPOWER_0_99_11"
        PATCH_URL=${PATCH_LEGACY_URL}

    elif [ ${OS_VER_MAJOR} -ge 21 ]
    then
        echo "--- Ubuntu version 21 or above detected"
        PATH_UPOWERD="/usr/libexec"
        UPOWER_BRANCH="UPOWER_0_99_11"
        PATCH_URL=${PATCH_LEGACY_URL}

    elif [ ${OS_VER_MAJOR} -le 20 ]
    then
        echo "--- Ubuntu version 20.04 or lower detected"
        PATH_UPOWERD="/usr/lib/upower"
        UPOWER_BRANCH="UPOWER_0_99_11"
        PATCH_URL=${PATCH_LEGACY_URL}
    fi
else  
    echo "-- Unknown system; this script was only tested on ubuntu and manjaro."
    exit 1
fi  
echo "------------------------------"  
echo


# Download upowerd source and selects the proper branch
#
cd ~  
git clone https://gitlab.freedesktop.org/upower/upower

if [ -z ${UPOWER_BRANCH} ]  
then  
    echo "-- Using latest master branch (0.99.12 or above)"
    cd upower/src
else  
    echo "-- Using branch ${UPOWER_BRANCH} (latest compatible with your distro)"
    cd upower
    git fetch --all --tags
    git checkout tags/${UPOWER_BRANCH} -b ${UPOWER_BRANCH}
    cd src
fi


# Download and patch upowerd
#
wget ${PATCH_URL} -O ${PATCH_NAME}  
if [ "$1" == "-keyboard" ] || [ "$1" == "--keyboard" ]; then  
        SILENCE_KEYBOARD="+     if ((type == UP_DEVICE_KIND_MOUSE || type == UP_DEVICE_KIND_KEYBOARD) && state == UP_DEVICE_STATE_DISCHARGING) {"
        sed -i "/UP_DEVICE_KIND_MOUSE/c${SILENCE_KEYBOARD}" ${PATCH_NAME}
fi  
patch -F 1 < ${PATCH_NAME}


# Compile upowerd
#
cd ..  
./autogen.sh
./configure
make


# Install upowerd
#
CUR_DATETIME=`date +%Y-%m-%d-%H%M%S`

pushd .  
cd src/.libs  
strip upowerd  
sudo chown root.root upowerd  
sudo mv upowerd ${PATH_UPOWERD}/upowerd-silent  
cd ${PATH_UPOWERD}  
sudo mv upowerd upowerd-original-${CUR_DATETIME}  
sudo ln -s upowerd-silent upowerd  
popd


# Install upower
#
pushd .  
cd tools/.libs  
strip upower  
sudo chown root.root upower  
sudo mv upower ${PATH_UPOWER}/upower-silent  
cd ${PATH_UPOWER}  
sudo mv upower upower-original-${CUR_DATETIME}  
sudo ln -s upower-silent upower  
popd


# Restart upowerd
#
sudo systemctl restart upower


# Compare versions before/after (they will likely be different, but it depends on what your distro packages by default)
#
echo  
echo "------------------------------"  
echo "upower version BEFORE the update:"  
echo "${UPOWER_ORIG_VER}"  
echo "------------------------------"  
echo "upower version AFTER the update:"  
upower --version  

For convenience, here's the script. You can run with:

wget -O - https://gist.githubusercontent.com/guiambros/166039459a8579638b57f7d135505ab1/raw/733b8dd3ac3280bb76f48ba3dc04655df6d69025/silent-mouse.sh | bash  

UPDATE: by default this disables mouse notifications only. If you want to disable keyboard notifications as well, run the script above passing --keyboard as a parameter. More specifically:

wget -O - https://gist.githubusercontent.com/guiambros/166039459a8579638b57f7d135505ab1/raw/733b8dd3ac3280bb76f48ba3dc04655df6d69025/silent-mouse.sh | bash -s -- --keyboard  

Now enjoy your low battery spam-free system :) Let me know in the comments below if it works for you.

1My old Performance MX uses a replaceable battery; the Performance MX 3 uses an internal non-replaceable battery that lasts even longer


Blog Logo

Gui Ambros

Maker, engineer, ad:tech veteran. Incurable optimist. I was there when the web was born. Opinions here are my own. @GuiAmbros


Published

Image

wrgms.com

/dev/random rants about technology, electronics, startups.

Back to Overview