The battery state of a wireless Keychron QMK-based keyboard can be displayed in the operating system

The short version: A wireless QMK-based Keychron keyboard can provide the information about the battery state, e.g. “81%”, to the operating system, just like, for example, a wireless computer mouse. Though the operating system may have to be configured for it to work, and it may not work for all Keychron keyboard models.

An example is a Keychron V6 Max on Ubuntu 22.04 (Jammy Jellyfish), after making some configuration changes in the operating system (it isn’t necessary to install any additional software). The battery state is shown in “Settings”“Power”, along with other wireless devices that provide the information, e.g., mice and headsets.

Introduction

On the subreddit r/Keychron, questions about displaying the battery state in the operating system for Keychron keyboards, like for other wireless devices, say mice and headphones, is an FAQ. But not much real information is usually provided.

Thus I decided to dig deeper. I couldn’t get it to work at all on Ubuntu 20.04 (Focal Fossa) using a prescribed way, including for mice and headsets for which it was expected to work. The keyboard didn’t provide the “Battery Percentage” line in the output from “info” in ‘bluetoothctl’.

But using a newer Ubuntu version (Ubuntu 22.04) and the described configuration change, I could get the battery to show in the GUI for both a ‘2.4  GHz‘ mouse, two Bluetooth headsets, and a Keychron V6 Max keyboard.

The charge state can be displayed on the Keychron keyboard itself by Fn + B, but this is about the information being transferred to the computer and being shown in the GUI.

The configuration change in Linux

It is essentially as in here. The value-add here is to test it on particular versions of Ubuntu, and for particular Keychron keyboards to find out if and where it actually works (or not). Also, caveats and testing steps are provided to be confident it will work (instead of only doing blind configuration changes).

It can be done as (from the command line):

sudo vi /etc/bluetooth/main.conf

In file main.conf, add a line with this content:

Experimental = true

Notes:

  1. The line should be in the “[General]” section, not, for example, the “[Policy]” section.
  2. Proficiency in using vi or Vim is presumed (including quitting it…). If not, use some other editor, like Geany. But it must be run with administrator privileges (in order to make changes to file main.conf), and this may change an application’s normal behaviour… (because it is run as another user)

Then, from the command line, restart the Bluetooth service in order to apply the change (alternatively, restart the computer):

sudo systemctl restart bluetooth

Check that the line with “Experimental” is accepted:

systemctl status bluetooth

The output should not contain “Unknown key Experimental for group General”.

Note that, despite this 2019-05-03 Stack Overflow answer, it actually does work on Ubuntu 22.04 (or at least the ‘dbus-send’ line didn’t work at all (“Error org.freedesktop.DBus.Error.InvalidArgs: No such interface ‘org.bluez.Battery1′”)).

Test that the battery status information is provided by the device

First power on and pair the Bluetooth devices. And test that they work in normal operation.

A gotcha: Only connect one Bluetooth headset at a time… For testing each headset in turn, power the other headsets off.

From the command line, identify the devices (and get their MAC addresses for use in subsequent steps):

bluetoothctl devices

Sample output:

Device 20:74:CF:51:62:CA Titanium by AfterShokz
Device 00:02:3C:9C:29:CF Zen Hybrid (SX:<C@FrxG'fK)
Device E5:EF:C8:61:40:DF Keychron V6 Max
Device 6C:93:08:65:8E:E6 Keychron K5 Pro

Note that this output also contains information about devices connected in the past, so a device’s presence in this list does not guarantee it will work (the response may be something like “Device E5:EF:C8:61:40:DF not available”). Also note that the MAC addresses may not be stable.

Test a device, for example “Keychron V6 Max”, for the presence of the battery state information:

echo -e "connect E5:EF:C8:61:40:DF\ninfo\n" | bluetoothctl

It can also be done interactively:

bluetoothctl
connect E5:EF:C8:61:40:DF
info

Sample output:

Device E5:EF:C8:61:40:DF (random)
   	Name: Keychron V6 Max
   	Alias: Keychron V6 Max
   	Appearance: 0x03c1
   	Icon: input-keyboard
   	Paired: yes
   	Trusted: yes
   	Blocked: no
   	Connected: yes
   	WakeAllowed: no
   	LegacyPairing: no
   	UUID: Generic Access Profile    (00001800-0000-1000-8000-00805f9b34fb)
   	UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)
   	UUID: Device Information        (0000180a-0000-1000-8000-00805f9b34fb)
   	UUID: Battery Service           (0000180f-0000-1000-8000-00805f9b34fb)
   	UUID: Human Interface Device    (00001812-0000-1000-8000-00805f9b34fb)
   	UUID: Vendor specific           (00010203-0405-0607-0809-0a0b0c0d1912)
   	Modalias: usb:v3434p0961d0113
   	ManufacturerData Key: 0x0006
   	ManufacturerData Value:
     03 00 80 4b 65 79 63 68 72 6f 6e 20 4b 42        ...Keychron KB
   	AdvertisingFlags:
     05                                               .
   	Battery Percentage: 0x56 (86)

In this case, the output contains a line with “Battery Percentage” (the very last line):

    Battery Percentage: 0x56 (86)

Which is interpreted as 86%.

The output also contains a line with “UUID: Battery Service (0000180F-0000-1000-8000-00805F9B34FB)”.

To extract just the battery state information (for MAC address E5:EF:C8:61:40:DF in this example):

echo -e "connect E5:EF:C8:61:40:DF\ninfo\n" | bluetoothctl | grep "Battery Percentage" 

And with a timestamp (for MAC address E5:EF:C8:61:40:DF in this example):

clear ; echo -n "Time: $(date +%FT%T_%N_ns)" ; echo -e "connect E5:EF:C8:61:40:DF\ninfo\n" | bluetoothctl | grep "Battery Percentage" 

Ifs and buts

In the test, it worked on Ubuntu 22.04, but not on Ubuntu 20.04. A reason could be a different version of BlueZ (use “bluetoothd -v” or “bluetoothctl -v”):

  • Ubuntu 20.04: 5.53
  • Ubuntu 22.04: 5.64
  • Ubuntu 24.04: 5.72

On Ubuntu 20.04, “systemctl status bluetooth” on the command line reports this error after the configuration change:

“bluetoothd[1432]: Unknown key Experimental for group General in /etc/bluetooth/main.conf”

In the test, it also only worked for a Keychron V Max series keyboard (V6 Max), but not for a K Pro series keyboard (K5 Pro ISO), which is probably not that surprising (test with, for example, ‘sudo btmgmt con‘). Both keyboards’ firmware was the newest (compiled from the newest source code (October 2024)).

GNOME may be the deciding factor

On a Ubuntu 20.04 system (with the same version of BlueZ, 5.53), but with Cinnamon as the desktop environment, the battery for the V6 Max showed up without any required configuration changes.

It could be due to D-Bus used in GNOME:

“…this specific GATT characteristic was moved into the D-Bus org.bluez.Battery1 interface.”

Or in other words, GNOME broke the battery indication. It seems to have been fixed in Ubuntu 24.04 (Noble Numbat); the battery indication worked out of the box, without requiring the configuration change as in Ubuntu 22.04 (Jammy Jellyfish).

On LMDE with Cinnamon, it worked out of the box. BlueZ version:

  • LMDE 6 and Cinnamon 6.4.6: 5.66

Cinnamon version: cinnamon –version from the command line (two single dashes before version (it will not work if pasted directly from here)).

Test conditions

Keyboard: Keychron V6 Max

Keyboard firmware: Compiled from close to the latest source code at the time (2024-10)

Keyboard Bluetooth firmware (for the Bluetooth module): version 0.1.13 (2024-01-08)

Results

The display in Ubuntu 22.04:


It may or may not be required to restart the computer before it takes effect.

Though the reading is not entirely consistent with the Fn + B indicator: At 85%, the indicator still shows 10/10 (100%). Only at 84% does it change to 9/10 (90%).

References

2 Comments on “The battery state of a wireless Keychron QMK-based keyboard can be displayed in the operating system

  1. Thanks.
    It looks like the issue with K Pro series keyboard is they don’t connect with BLE, but with BT Classic actually:
    $ sudo btmgmt con
    7C:1E:52:A8:89:77 type BR/EDR

    For BLE-capable devices (which Pro’s are claimed to be), the output should be something like:
    0C:EC:80:E6:4A:C3 type LE Random

    Could you check?

Leave a Reply

Your email address will not be published. Required fields are marked *

*