Skip to content

Instantly share code, notes, and snippets.

@mekb-turtle
Created October 6, 2024 06:18
Show Gist options
  • Save mekb-turtle/1701273f7b6feaf2fdc92d3ff3c1c950 to your computer and use it in GitHub Desktop.
Save mekb-turtle/1701273f7b6feaf2fdc92d3ff3c1c950 to your computer and use it in GitHub Desktop.
Arduino caps lock LED indicator

This script reads the state of the Caps Lock key and sends it to an Arduino connected to a serial port. The Arduino then controls an LED to indicate the state of the Caps Lock key.

The script can be run multiple times, but only one instance will be running at a time. If another instance is started, it will send a message to the running instance to update the state of the Caps Lock key.

If you use Hyprland, paste this into your config file:

bindrlti = , Caps_Lock, exec, $HOME/.bin/update-caps
exec-once = $HOME/.bin/update-caps
int ledG = 3, ledH = 4;
void setup() {
pinMode(ledG, OUTPUT);
pinMode(ledH, OUTPUT);
digitalWrite(ledG, LOW);
digitalWrite(ledH, LOW);
Serial.begin(9600);
}
void loop() {
if (!Serial.available()) return;
switch (Serial.read()) {
case '0':
digitalWrite(ledH, LOW);
break;
case '1':
digitalWrite(ledH, HIGH);
break;
}
}
#!/bin/env python
import os
import sys
import socket
import atexit
import evdev
from time import sleep
arduino_port = '/dev/serial/by-id/usb-1a86_USB_Serial-if00-port0'
keyboard_event = '/dev/input/by-id/usb-Logitech_USB_Receiver-if01-event-kbd'
pidfile = '/tmp/update-caps.pid'
socketfile = '/tmp/update-caps.sock'
if os.path.exists(pidfile):
with open(pidfile, 'r') as f:
pid = f.read()
if os.path.exists('/proc/' + pid):
# already running, send message to it instead
try:
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
sock.connect(socketfile)
sock.sendall('update'.encode('utf-8'))
except ConnectionRefusedError:
print("No running instance to send the message to.")
sys.exit(0)
os.unlink(pidfile)
tty = open(arduino_port, 'w')
sock = None
def cleanup():
if sock is not None:
sock.close()
tty.close()
if os.path.exists(pidfile):
os.unlink(pidfile)
if os.path.exists(socketfile):
os.unlink(socketfile)
atexit.register(cleanup)
with open(pidfile, 'w') as f:
f.write(str(os.getpid()))
if os.path.exists(socketfile):
os.unlink(socketfile)
def update_caps():
# Keep serial port open to avoid Arduino restarting
device = evdev.InputDevice(keyboard_event)
led_state = device.leds()
if evdev.ecodes.LED_CAPSL in led_state:
print("Caps Lock is on")
tty.write('1')
else:
print("Caps Lock is off")
tty.write('0')
tty.flush()
update_caps()
# wait 2 seconds for the Arduino to boot
sleep(2)
update_caps()
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.bind(socketfile)
sock.listen(1)
print("Listening for messages...")
while True:
conn, _ = sock.accept()
with conn:
data = conn.recv(1024)
if data:
if data.decode('utf-8') == 'update':
update_caps()
else:
print(f"Received unknown message: {data.decode('utf-8')}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment