60 lines
2.1 KiB
Python
Executable File
60 lines
2.1 KiB
Python
Executable File
import evdev
|
|
import json
|
|
import sys
|
|
import select
|
|
import os
|
|
|
|
class KeyboardLedMonitor:
|
|
def __init__(self):
|
|
self.last_state = {"caps": "0", "num": "0"}
|
|
self.kbd_devices = []
|
|
|
|
# ищем все устройства, которые умеют в CapsLock
|
|
devices = [evdev.InputDevice(path) for path in evdev.list_devices()]
|
|
for dev in devices:
|
|
capabilities = dev.capabilities().get(evdev.ecodes.EV_KEY, [])
|
|
if evdev.ecodes.KEY_CAPSLOCK in capabilities:
|
|
self.kbd_devices.append(dev)
|
|
|
|
if not self.kbd_devices:
|
|
sys.exit(1)
|
|
|
|
# выводим начальное состояние
|
|
self.push_update(self.kbd_devices[0])
|
|
|
|
def get_led_state(self, dev):
|
|
# проверяем коды
|
|
leds = dev.leds()
|
|
return {
|
|
"caps": "1" if 1 in leds else "0",
|
|
"num": "1" if 0 in leds else "0"
|
|
}
|
|
|
|
def push_update(self, dev):
|
|
# отдаем json в stdout при изменении
|
|
current_state = self.get_led_state(dev)
|
|
if current_state != self.last_state:
|
|
sys.stdout.write(json.dumps(current_state) + "\n")
|
|
sys.stdout.flush()
|
|
self.last_state = current_state
|
|
|
|
def run(self):
|
|
# создаем мапу файловых дескрипторов для селектора
|
|
devices_dict = {d.fd: d for d in self.kbd_devices}
|
|
|
|
try:
|
|
while True:
|
|
# ждем событий от любого из устройств
|
|
r, _, _ = select.select(devices_dict, [], [])
|
|
for fd in r:
|
|
dev = devices_dict[fd]
|
|
for event in dev.read():
|
|
# если прилетело событие изменения светодиода
|
|
if event.type == evdev.ecodes.EV_LED:
|
|
self.push_update(dev)
|
|
|
|
except (PermissionError, KeyboardInterrupt):
|
|
sys.exit(0)
|
|
|
|
if __name__ == "__main__":
|
|
KeyboardLedMonitor().run() |