Emojinator 🤖

Alai Miranda
10 min readMar 26, 2023

El 10 de febrero asistí con las amigas de Mujeres a Seguir y Globant al colegio Margaret Thatcher de Barajas para contarle a un grupo de chicos y chicas de 11 y 12 años cuál había sido mi experiencia con la tecnología desde que tenía su edad.

Cuando me invitan a este tipo de actividades suelo mostrar proyectos que he desarrollado desde que comencé a experimentar con el mundo STEM: Alibubu, Maniquí180, Luk, AhíVieneLaISS, así como diversos prototipos que he fabricado en impresión 3D como el Docuscopio y otras iniciativas como esvuela.com e impresiónadictiva3d.com.

Los estudiantes del colegio Margaret Thatcher fueron uno de los grupos más interesados con los que he podido compartir. Muchas manos alzadas e intervenciones durante mi charla, pero al final me sorprendió que, aunque podían irse al recreo, la gran mayoría se quedó para hacerme más preguntas e interactuar con Luk, Alibubu, AhíVieneLaISS o una mano fabricada en una impresora 3D.

Había mucho interés y un número limitado de proyectos, por lo que me quedé pensando en que debía agregar una nueva actividad con la que los pequeños asistentes pudieran interactuar y, lo más importante, llevarse un recuerdo a casa.

Durante el confinamiento compramos un Stream Deck de Elgato. Se trata de un dispositivo de hardware diseñado para la producción de contenido en vivo, especialmente en la transmisión de videojuegos y streaming. Tiene una serie de botones programables con pantalla LCD que permiten al usuario controlar una amplia variedad de acciones con un solo clic. Los botones se pueden personalizar con iconos específicos y nombres de acciones para que el usuario pueda acceder fácilmente a funciones específicas de software, como cambiar de escena en OBS, ajustar el volumen del micrófono, activar efectos de sonido, entre otras.

También tenía una impresora térmica de tickets razonablemente pequeña y un Raspberry Pi. Siempre tengo un Raspberry Pi. Me quedaba pensar en el proyecto. Estos tres componentes representan la combinación ideal porque son fáciles de transportar. No necesito pantalla, teclado ni ratón. Puedo llevarlos, conectarlos entre sí, la impresora y el Raspberry Pi a la toma de energía y a jugar.

Emojinator

Se me ocurrió entonces poder convertir cada uno de los botones en emojis que al presionarlos aparecieran impresos en tickets que todos los asistentes podrían llevarse. Nuestro Stream Deck es la versión de 15 botones. Podía dedicar 14 botones a emojis y uno para apagar el Raspberry Pi cuando terminara la actividad, ya que no se recomienda desconectar ningún ordenador, incluyendo los Raspberry Pi, sin apagarlo con el shutdown correspondiente.

En la actualidad existen más de 3.500 emojis de objetos, animales, símbolos, banderas, alimentos, actividades y emociones, entre otros. Tenía que buscar la manera de poder imprimir más de 14 emojis. Los Stream Deck permiten tener hasta 10 pantallas diferentes y cualquiera de los botones puede utilizarse para navegar entre cada una de ellas.

Decidí utilizar la primera pantalla para mostrar categorías de emojis. Al presionar cada botón aparecería un nuevo conjunto de emojis específicos. Necesitaba un par de botones para navegar entre categorías. De esta forma podía tener 8 pantallas con 13 emojis para un total de 104 graciosas imágenes y una pantalla final, la décima, con funciones administrativas como el apagado del Raspberry Pi.

Los emojis elegidos fueron de las categorías caras 🙂, manos 👋, animales🐕, comida 🍉, deportes 🍉, objetos 📺, vehículos 🚀 y ropa 🧥. Son los que aparecen en la primera pantalla del Stream Deck.

Ahora necesitaba los archivos de 104 emojis. Cada empresa o producto tiene su propio conjunto de emojis. Apple, Google, Microsoft, WhatsApp, Facebook y Twitter, entre otros. Ya que algunos son propietarios y ni pagando pueden usarse, he utilizado Twemoji, los emojis de código abierto de Twitter que, mientras Elon Musk no diga lo contrario, son gratis. Bajé entonces todos los archivos en formato SVG o gráficos vectoriales escalables.

De cada emoji necesitaba dos archivos distintos, el SVG que se mostraría en los botones del Stream Deck y el PNG para poder imprimirlo. Por ejemplo, el emoji de la fresa 🍓:

1f353.svg
1f353.png

Para poder tener la versión PNG del SVG tuve que instalar el programa rsvg-convert. Pero tenía que darle un tamaño máximo que pudiera imprimirse. Después de varias pruebas para la capacidad de 80mm de la impresora encontré que el tamaño máximo aceptado era de 350 pixels de alto:

pi@emojinator:~ $ rsvg-convert -h 350 1f353.svg > 1f353.png

Ya tenemos el hardware (Stream Deck + impresora + Raspberry Pi) y los emojis. Ahora necesitamos el software y les tengo dos noticias; una buena y otra mala.

Software

La buena es que el programa lo hice en Python 🐍. A piece of cake por lo que este punto lo dejo para el final. La mala es que Stream Deck requiere una aplicación especial que Elgato ha desarrollado para Windows y MacOS (el sistema operativo de las Macs de Apple). Como sabéis el SO principal de las Raspberry Pi es Raspberry Pi OS (anteriormente se llamaba Raspbian), una versión de Linux libre y gratuita basada en Debian.

El Stream Deck se conecta al ordenador a través de uno de los cuatro puertos USB disponibles, como lo haría un ratón o un teclado de no ser inalámbricos. La aplicación oficial (Elgato Stream Deck Software for Mac o for Windows) traduce el clic sobre los botones en acciones que se ejecutarán en el ordenador como por ejemplo:

  • Acciones de teclado: escribir texto, pulsar combinaciones de teclas y simular pulsaciones de teclas.
  • Acciones multimedia: reproducir, pausar y saltar pistas de audio y vídeo.
  • Acciones de aplicación: abrir y cerrar aplicaciones, cambiar entre aplicaciones, y ajustar la configuración de aplicaciones específicas.
  • Acciones web: abrir páginas web y enviar comandos HTTP/HTTPS.
  • Acciones de sistema: apagar y reiniciar el sistema, activar el protector de pantalla y ajustar la configuración del sistema.

Elgato no ha desarrollado una versión para equipos Linux pero, como este mundo es maravilloso, encontré en GitHub el repositorio StreamdeckUI creado por Timothy Edmund Crosley: Linux Compatible UI for the Elgato Stream Deck.

La versión TL;DR de lo que pasó después, durante un par de semanas, incluye múltiples instalaciones de Raspbian (perdón, Raspberry Pi OS) en sus versiones Bullseye y Buster de 32-bit, varias pruebas sobre Python 2.x y 3.x, intentos con contenedores de Docker y nada. No había manera de que StreamdeckUI corriera en mi Raspberry Pi 4 con 4 GB de RAM.

Comenzaba a desesperarme cuando finalmente llegué a la solución. Resulta que StreamdeckUI necesita la librería PySide2, la cual a su vez requiere la versión 64-bit de Bullseye según el post PySide2 on PIOS64 bullseye — build (streamdeck-ui) en el foro oficial de Raspberry Pi. Great!

Pero, aunque fue fácil resolverlo, surgió otro problema con los permisos de escritura a la impresora. Tenía que averiguar cuál era el identificador del dispositivo asociado a la impresora o “lp” ya que cuando enviaba el emoji recibía un mensaje de error.

Primero busqué el ID y luego garanticé permisos de lectura (r) y escritura (w) al line printer. “lp” significa “line printer”, que hace referencia a las antiguas impresoras de línea que eran comunes en los primeros ordenadores. Hoy en día, “lp” se refiere al sistema de impresión y al conjunto de herramientas y comandos utilizados para administrar las impresoras en Linux, incluyendo el comando para enviar trabajos de impresión a través del sistema.

pi@emojinator:~ $ ls -la /dev/bus/usb/001/
total 0
drwxr-xr-x 2 root root 120 Aug 7 2022 .
drwxr-xr-x 4 root root 80 Jan 1 1970 ..
crw-rw-r — 1 root root 189, 0 Mar 25 13:22 001
crw-rw-r — 1 root root 189, 1 Mar 25 13:22 002
crw-rw-rw- 1 root lp 189, 2 Mar 25 13:22 003
crw-rw-r — + 1 root root 189, 3 Mar 26 12:15 004

pi@emojinator:~ $ sudo chmod a+rw /dev/bus/usb/001/003

A estas alturas, ya puedo ejecutar en el Raspberry Pi la aplicación que emula a Elgato Stream Deck Software for Mac o for Windows; una interfaz gráfica que permite definir las acciones de cada uno de los botones, indicando además la imagen que lo acompañará, pero quizá la función más importante es la de actuar como intermediario entre el Stream Deck y el sistema operativo al traducir cada clic en una acción específica previamente definida. En nuestro caso, imprimir el emoji de nuestra preferencia.

Pero había un pequeño detalle, todo estaba funcionando con un Raspberry Pi que tenía su pantalla, ratón y teclado conectados e iniciando la aplicación manualmente desde la línea de comandos o CLI.

Headless

Cuando se habla de Raspberry Pi, “headless” significa que el dispositivo se utiliza sin una pantalla, teclado o ratón conectados directamente a él. El Raspberry Pi se configura y controla a través de una conexión de red (por ejemplo, Wi-Fi o Ethernet) y una conexión o acceso remoto, como SSH (Secure Shell). La configuración headless es común en situaciones en las que es difícil o innecesario conectar una pantalla y otros periféricos al Raspberry Pi.

En el caso del Emojinator, al igual que con Luk o AhíVieneLaISS, no necesito pantalla, ratón, ni teclado. Simplemente quiero poder llevar con facilidad los mínimos componentes necesarios, realizar su instalación en el salón donde vaya a conversar, conectar, encender y listo.

Ya que no tendré pantalla, teclado, ni ratón, necesito uno de los siguientes métodos para iniciar programas de forma automática en el Raspberry Pi: rc.local, systemd, init.d, cron o .bashrc. Luk y AhíVieneLaISS funcionan gracias a un archivo /etc/rc.local donde, simplemente, debía incluir el nombre de la aplicación antes de la línea “exit 0”.

Modifico rc.local, incluyendo primero los permisos de rw a la impresora y a continuación el inicio de la aplicación, lo guardo, salgo, reboot (sin desconectar pantalla, ratón, ni teclado) y espero… Nada, los emojis no aparecían en los botones del Stream Deck, en otras palabras, la aplicación no se estaba iniciando de forma automática.

Decido publicar el issue Headless mode not working on Raspberry Pi 4 en el repositorio streamdeck_ui de Timothy Crosley en GitGub. Me responde Pieter Venter (dodgyrabbit) haciendo referencia a un comentario de kda titulado implement — no-ui with no X available. Encuentro modificaciones que no han sido integradas al repositorio. Modifico la app con la esperanza de que funcionara. Nada.

Sigo investigando. Leo en Wikipedia que “systemd se puede utilizar como un sistema de inicio de Linux (el proceso init llamado por el núcleo o kernel de Linux para inicializar el espacio de usuario durante el proceso de arranque de Linux y gestionar posteriormente todos los demás procesos”. Es más moderno y más completo que rc.local ya que proporciona un control más avanzado sobre los servicios del sistema y es más adecuado para iniciar servicios complejos y dependientes. Aseguran que rc.local es una solución más simple y tradicional para iniciar programas en el arranque del sistema. Es menos complejo que systemd y es más adecuado para tareas sencillas. Aparentemente, si el programa no requiere de configuraciones avanzadas ni depende de otros servicios del sistema, rc.local puede ser la opción más sencilla y fácil de configurar.

Decido utilizar rc.local y systemd incluyendo el sencillo permiso a la impresora en el primero y la llamada a la aplicación en el archivo emojinator.service:

[Unit]
Description=emojinator
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/pi/.local/bin/streamdeck -n
Restart=always
User=pi
Group=pi

[Install]
WantedBy=default.target

Habilito el servicio:

pi@emojinator:~ $ systemctl — user enable emojinator.service

Y de nuevo reboot (sin desconectar pantalla, ratón, ni teclado) y a esperar. Nada, la aplicación sigue sin iniciarse de forma automática. Reviso el estado del servicio:

pi@emojinator:~ $ systemctl — user status emojinator.service

Failed to determine supplementary groups: Operation not permitted
Failed at step GROUP spawning /usr/bin/python3: Operation not permitted
Control process exited, code=exited, status=216/GROUP

Googleo de nuevo para encontrar que no debía indicar el usuario ni el grupo en el archivo emojinator.service. Se queda así:

[Unit]
Description=emojinator
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/pi/.local/bin/streamdeck -n
Restart=always

[Install]
WantedBy=default.target

Reinicio con todos los periféricos de entrada y salida conectados. Suspenso. Funciona. ¡Funciona!

Shutdown. Desconecto power supply. Retiro pantalla, teclado y ratón. Conecto power supply.

¡FUNCIOOOONAAAAAAA!

Ha pasado más de un mes desde mi visita al colegio Margaret Thatcher de Barajas. 42 días en total. Ha sido uno de los proyectos más complejos que he terminado. Tuve que investigar sobre los emojis, formatos de imágenes, conversiones, contenedores, versiones de Raspberry Pi OS, 32-bit y 64-bit, diferencias entre Python 2.x y 3.x, protocolos, permisos y librerías de impresión, nuevos comandos de Linux, entre otros. Hacer el programa era solo una de las tareas.

¿Piece of cake dije?

Respecto al programa en Python os mencioné que había sido lo más fácil. Básicamente necesitaba una aplicación que aceptara el ID del emoji como parámetro en la línea de comandos, ubicara el archivo que tuviera ese nombre en la carpeta de emojis, abriera un canal de comunicación con la impresora, enviara el archivo a la impresora térmica de tickets y listo.

Tuve que realizar mil pruebas de impresión. Creo que gasté un rollo de papel térmico. Fueron muchas impresiones. Pero valió la pena.

Ahora tan solo me queda subir el programa a GitHub y esperar la próxima visita a un colegio lleno de estudiantes a quienes trataré de “imprimirles” el emoji de la curiosidad por el mundo STEM.

Alai Miranda

--

--