"Después del juego es antes del juego"
Sepp Herberger

jueves, 1 de diciembre de 2022

Interruptor casero USB.

Vamos a ver como construir un interruptor casero que se conecta por USB y que al pulsarse permite lanzar un evento en el ordenador, ejecutando un script.

Lo primero es construir el interruptor: ¿que usar si no tenemos ni idea de electrónica?. Pues no hace falta nada especial ya que con un ratón de ordenador es suficiente. Todos tenemos ratones USB rotos o antiguos que podemos reciclar. La idea es desmontar el ratón, sacar la placa, arrancar la luz led y verificar que el botón central (el asociado al click de la rueda) funciona y manda señal por el cable USB. Da igual el estado del resto de mecanismos.

Cogemos el ratón, lo metemos dentro de una cajita del tamaño adecuado y lo pegamos usando la pistola térmica de silicona que tenemos todos para las manualidades. En mi caso tenía una cajita que venía perfecta:
Nótese como buscamos que el interruptor del botón quede justo en el centro (marcado con el círculo amarillo). Luego he puesto una tapa de plástico agujereada para permitir llegar al interruptor y forrada con goma eva. Por último hago un interruptor externo con un tapón y un poco de espuma de embalaje. La idea es que el interruptor externo presione al interruptor interno del ratón.
Una vez pegado y montado todo:
Creo que es resultón para lo que yo quiero, pero si queremos hacerlo mas formal siempre podemos usar la impresora 3D para generar una cajita y botón con aspecto mas profesional.

Ya tenemos el hardware, vamos al software. Pinchamos el cable en un puerto USB y el Linux lo detecta como un ratón, pero como esta casi todo inutilizado tan solo recibirá eventos del botón central. Lo primero es encontrar el generador de eventos asociado al nuevo ratón:
# ls -l /dev/input/by-id
total 0
lrwxrwxrwx 1 root root  9 oct 27 09:34 usb-0461_USB_Optical_Mouse-event-mouse -> ../event2
lrwxrwxrwx 1 root root  9 oct 27 09:34 usb-0461_USB_Optical_Mouse-mouse -> ../mouse0
lrwxrwxrwx 1 root root  9 oct 27 09:34 usb-CHICONY_HP_Basic_USB_Keyboard-event-kbd -> ../event3
lrwxrwxrwx 1 root root 10 nov 29 13:32 usb-Logitech_USB-PS_2_Optical_Mouse-event-mouse -> ../event14
lrwxrwxrwx 1 root root  9 nov 29 13:32 usb-Logitech_USB-PS_2_Optical_Mouse-mouse -> ../mouse1
En nuestro caso sería /dev/input/event14. El paso siguiente es verificar que se detectan los eventos de pulsación. Para ello usamos triggerhappy:
# apt-get install triggerhappy
# thd --dump /dev/input/event14
Y pulsamos varias veces el interruptor para ver si se detecta. En consola debería mostrarse:
EV_KEY	BTN_MIDDLE	1	/dev/input/event14
# BTN_MIDDLE	1	command
EV_KEY	BTN_MIDDLE	0	/dev/input/event14
# BTN_MIDDLE	0	command
EV_KEY	BTN_MIDDLE	1	/dev/input/event14
# BTN_MIDDLE	1	command
thd --dump /dev/input/event14
EV_KEY	BTN_MIDDLE	0	/dev/input/event14
# BTN_MIDDLE	0	command
Perfecto: el evento generado por la pulsación del botón es "BTN_MIDDLE 1". Conviene recalcar en este momento que la pulsación del botón central del ratón puede ser también interceptado por nuestro entorno de escritorio Linux y provocar algún efecto asociado (por ejemplo, pegar el texto que hay en el portapapeles). Para evitar efectos colaterales recomendamos desactivar ese ratón en la configuración del entorno de escritorio:

Una vez tenemos el evento localizado, creamos la configuración que asocia dicho evento al lanzamiento de un script:
# cat /etc/triggerhappy/triggers.d/redbutton.conf
BTN_MIDDLE    1       /root/scripts/redbutton.sh
Después de este cambio de configuración se debe reiniciar el servicio triggerhappy, pero antes debemos configurarlo para que se ejecute como root (normalmente lo hace como nobody) y escuche solo los eventos que vengan de /dev/input/event14.

Inocente de mi, probé a modificar tanto /etc/default/triggerhappy como /etc/init.d/triggerhappy sin éxito. Seguia ejecutándose con el usario nobody y escuchando en /dev/input/event*. Esto lo podemos verificar haciendo:
# ps aux | grep thd
nobody   12523  0.1  0.0  43844  2852 ?        Ss   21:32   0:00 /usr/sbin/thd --triggers /etc/triggerhappy/triggers.d/ --socket /run/thd.socket --user nobody --deviceglob /dev/input/event*
La causa de esto es que en Ubuntu 18 el demonio triggerhappy se lanza realmente desde /lib/systemd/system/triggerhappy.service. Los otros dos ficheros están de adorno. No entiendo esta manía de tener servicios que están init.d y en systemd a la vez, es como si hubiesen quedado el trabajo a medias y se hubiesen ido de cañas.

Editamos /lib/systemd/system/triggerhappy.service y lo quedamos:
[Unit]
Description=triggerhappy global hotkey daemon
After=local-fs.target

[Service]
Type=notify
ExecStart=/usr/sbin/thd --triggers /etc/triggerhappy/triggers.d/ --socket /run/thd.socket --user root --deviceglob /dev/input/event14

[Install]
WantedBy=multi-user.target
Luego reiniciamos el servicio:
# service triggerhappy restart
Y bueno ahora nos falta escribir el script. Aqui podemos poner cualquier cosa, yo simplemente voy a hacer que se oiga un audio (descargado de Internet o generado con pico2wave) en el escritorio:
# cat /root/scripts/redbutton.sh 
#!/bin/bash

#Subimos el volumen al máximo en el alsamixer
amixer set Master unmute
amixer set Master 100%

#Si hay un usuario logado, conectamos con su pulseaudio para subir el volumen al máximo
user=$(who | grep "(:0)" | head -1 | cut -f1 -d" "); 
if  [ -n "$user" ]
then
  su $user -c "DISPLAY=:0 pactl set-sink-volume 0 150%"
  su $user -c "DISPLAY=:0 pactl set-sink-mute 0 0"
  cp -f /root/scripts/no.wav /tmp/no.wav
  su $user -c  "DISPLAY=:0 aplay /tmp/no.wav"
else
  cp -f /root/scripts/no.wav /tmp/no.wav
  DISPLAY=:0 aplay /tmp/no.wav
fi

exit 0
Con esto ya tenemos todo funcionando. Bien, y ahora la pregunta: ¿Para qué carajos quiero esto?. Bueno, pues aparte de para enredar, para conectarlo a una Raspberry Pi o un OpenWRT sin teclado/ratón y poder lanzar eventos sobre ellos: apagar/encender la wifi, hacer una foto con la webcam, reiniciar un servicio o una aplicación, etc.

En mi caso tengo una Rasbperry Pi mostrando una página web en modo kiosko con información en tiempo real. A veces el navegador se bloquea y hay que cerrarlo y abrirlo de nuevo, teniendo que conectarme por VNC y hacer el proceso a mano. Con un botón de este tipo puedo lanzar un script que permite a cualquiera reiniciar el navegador en todo momento.

Out!

No hay comentarios:

Publicar un comentario