Use a Keyboard as Home Assistant Switch/Button

Hey guys,

First of all: sorry for my bad English — it’s not my native language.

I’ve been working on my Home Assistant setup for two months now, and everything is working pretty well so far.

Sadly, my journey to Home Assistant wasn’t a direct one.

First, I got an iPhone as a gift. Then I decided to try out home automation, so I bought a few Apple products (the cheaper ones).
After that, I discovered there aren’t many devices available with HomeKit certification. Then I learned about Matter. Then about Homebridge. Yada yada.

After all that, I decided to start fresh with Home Assistant. Right now, everything is working — with a bit of tinkering and a few workarounds.

Only one device (and it’s an expensive one) is giving me trouble. It works, but it’s painfully slow.

It’s the ONVIS Switch HS2, a multi-state button with 5 buttons.

The real downside of this device is that it only works via Wi-Fi.

At first, I used this device in my office to control things like my PC, desk lamp, printer, TV, etc.

But after a day or two — or sometimes randomly — it would become incredibly slow. You’d press a button and have to wait at least 30 seconds for the action to execute.

So, I started searching for a solution.

After hours (and days) of experimenting, I found one.

My first attempt was using an old Raspberry Pi 4 running Raspbian with XFCE. I set up keyboard shortcuts via XFCE. It worked — but it was way too complicated.

Then I tried something without a GUI or X server, just using Bash. That only worked about 50% of the time.

As a last resort, I gave up and asked ChatGPT how to create a dedicated keyboard listener just for a Python script — and lol, that gave me a fast solution. Not perfect, but after some tinkering, I now have a working setup.

What you need:

Any kind of Raspberry Pi (I'm using an old Pi 3 now)

A spare keyboard just for the Raspberry Pi

Raspbian or another OS installed on the Pi

You’ll need these two files:

hotkeys_listener.py


from evdev import InputDevice, categorize, ecodes
import subprocess

def load_hotkeys(path='/home/user/hotkeys.conf'):
    hotkeys = {}
    with open(path, 'r') as f:
        for line in f:
            line = line.strip()
            if not line or '=' not in line or line.startswith('#'):
                continue
            combo, cmd = map(str.strip, line.split('=', 1))
            key_tuple = tuple(k.upper() for k in combo.split('+'))
            hotkeys[key_tuple] = cmd
    return hotkeys

device_path = '/dev/input/by-path/platform-3f980000.usb-usb-0:1.5:1.0-event-kbd'  # anpassen
dev = InputDevice(device_path)

hotkeys = load_hotkeys()
print("Geladene Hotkeys:", hotkeys)

pressed_keys = set()

normalization = {
    'KEY_LEFTCTRL': 'CTRL',
    'KEY_RIGHTCTRL': 'CTRL',
    'KEY_LEFTALT': 'ALT',
    'KEY_RIGHTALT': 'ALT',
    'KEY_LEFTSHIFT': 'SHIFT',
    'KEY_RIGHTSHIFT': 'SHIFT',
}

print("Starte Hotkey Listener...")

for event in dev.read_loop():
    if event.type == ecodes.EV_KEY:
        key_event = categorize(event)
        keycode = key_event.keycode
        if isinstance(keycode, list):
            keycode = keycode[0]
        keycode = keycode.upper()

        if keycode in normalization:
            keycode = normalization[keycode]
        elif keycode.startswith('KEY_'):
            keycode = keycode[4:]  # 'KEY_F1' -> 'F1'

        print(f"Key event: {keycode} - State: {key_event.keystate}")

        if key_event.keystate == key_event.key_down:
            pressed_keys.add(keycode)

            for combo, cmd in hotkeys.items():
                if all(k in pressed_keys for k in combo):
                    print(f"Erkannt: {'+'.join(combo)} → {cmd}")
                    subprocess.run(cmd, shell=True)

        elif key_event.keystate == key_event.key_up:
            pressed_keys.discard(keycode)

hotkeys.conf (example)


CTRL+F1 = curl -X POST http://192.168.5.134:8123/api/webhook/pc-schalten-7Jvo5p2pjZFshr8cE_uguLOL
CTRL+F2 = curl -X POST http://192.168.5.134:8123/api/webhook/fernseher-buro-schalten-E6_RwqqEfSzgEjTvK8yREX2P
CTRL+F3 = curl -X POST http://192.168.5.134:8123/api/webhook/schreibtischlampe-schalten-zSmhj4TFmE79d5_lraEpSKBK
CTRL+F4 = curl -X POST http://192.168.5.134:8123/api/webhook/li-on-schalten-2-lf8rvZP2ZFVX48L8VN4P1iRq
CTRL+F5 = curl -X POST http://192.168.5.134:8123/api/webhook/aktenvernichter-schalten-_XISa5kHjvFs9wzblGd5EU4O
CTRL+F6 = curl -X POST http://192.168.5.134:8123/api/webhook/drucker-schalten-UCEyGZpNZkDi9B-irR7ve-KH
CTRL+1 = curl -X POST http://192.168.5.134:8123/api/webhook/kvm1-schalten-tmkOAXZWaAqkxbFwmLA5my_d
CTRL+2 = curl -X POST http://192.168.5.134:8123/api/webhook/kvm2-schalten-ady-Z19YPX_F-HAchBcwOffo
CTRL+3 = curl -X POST http://192.168.5.134:8123/api/webhook/kvm3-schalten-Q9nbV89iNdrpw4VqNt2NgPyq
CTRL+4 = curl -X POST http://192.168.5.134:8123/api/webhook/kvm4-schalten-cxAm5sP_hLL043LDeV3h9slh

And it works extremely fast.

Thanks for your patience with my English! If you have any questions — feel free to ask :blush:

PS: i decided to ask ChatGPT again to correct this text lol.

This only works, if the Keyboard is directly connected to the Home Assistant Instance.

In my case, i would need atleast a 70 meter long USB extension to connect the keyboard from my office to the Basement where my rack is :sweat_smile:

Or, you run a secound Home Assistant on a Rpi / seperate Machine and than use it to control the first HA Instance.

Are you sure about that? https://www.youtube.com/watch?v=YV0DFPBQbWQ

Yes. Thanks for the Video. It gived me inspiration about to make Stickers :smiley:

The Numpad from the Guy in the Video, is connected directly to his Homeassistant Instance (in his case a raspberry pi running HA).

But my Homeassistant Instance, runs on a VM, on a Server, wich is in the Basement two stories under my office.

It is connected via a wireless adaptor.

1 Like

Again, directly to the Homeassistant Instance. The Transportmedium didnt matter.