Jakub Jirůtka | OpenAlt 2025
Electronic door signs
at FEL CVUT
System engineer and developer
Works at FEE CTU in Prague
FOSS developer & contributor
Alpine Linux developer
$~ whoami
Source: https://lezebre.lu/en/sticker-simons-cat-claws/

@jirutka
@jakub@jirutka.cz
jakub@jirutka.cz
Source: ChatGPT 5 (DALL-E 3)

Source: ChatGPT 5 (DALL-E 3)




Cat by: ChatGPT 5 (DALL-E 3)
- expensive updates (paper, ink, and human labour)
- doesn’t display non-periodic events
- block teaching
- exams
- reservations
- “what’s happening now” lookups are not O(1)
Limitations
- display complete, up-to-date information
- lessons, exams, reservations, study room
- display what’s happening now / in <15 min + today
- remote control
- two power options:
- over Ethernet (available in newly renovated rooms)
- battery → LCD display is not an option
- sufficiently large and legible display
- frame printable on a standard 3D printer (e.g. Prusa MK3)
What we wanted


First prototypes


First lessons learned
- 7.5” displej is too small
- standard PoE (Power-over-Ethernet) is problematic:
- PoE converters are quite large
- RJ45 is quite large
- PoE emits a lot of heat (48 V → 5 V)
- Ethernet cable is firm
- standard electrical installation box is small
- gesture control doesn’t work well with e-ink
- long delay is confusing for users
Source: ChatGPT 5 (DALL-E 3)


Cat by: ChatGPT 5 (DALL-E 3)






- 10.2” e-ink, 2-bit grayscale
- ESPink v2 (ESP32 board)
- (10 Ah LiPol battery)
- custom firmware
- custom 3D printed frame
Final version


-
ESP32-WROOM-32 16 MiB
- Xtensa dual-core 32-bit LX6 240 MHz
- 448 kiB ROM / 520 kiB SRAM / 16 MiB SPI flash
- 802.11b/g/n (WiFi), Bluetooth V4.2 & BLE
- EPD connector (SPI)
- USB-UART converter
- LDO regulator (3.7–8 V)
- battery charger
- USB-C for programming and power
-
open hardware
- https://github.com/LaskaKit/ESPink

ESPink v2
Power Supply
Battery
- 10 Ah LiPol
- last for 6–12* months
- can be installed anywhere
Power over Ethernet
- passive PoE 7 V
- last “forever”
- requires Ethernet




Frame

Frame
Inspired by Vlad Waas’ 7.5” Bauhaus frame for Živý obraz.
- reverse-engineered from STLs in FreeCAD
- scaled for 10.2” display
- two snap fits replaced with screw clips
- adapted for wall mounting
- added spacer corners
- added side reset switch
- many small adjustments

Frame (assembled)

Top part (bottom view)

Bottom part (top view)

Middle part
Architecture
“Timetable API”
Door Signs Controller
Grafana
Prometheus
MQTT broker
HTTP server
NTP server
HTTPS
MQTT
HTTPS
NTP
MQTT
firmware → (OTA update)
HTTPS
PNG, settings →
← telemetry, logs
metrics
Energy saving
Controller sends the image to be displayed, along with a timestamp indicating when the next update is expected.
ESP wakes up, renders the image, sets the timer and goes into deep sleep.
- in C/C++
- based on Arduino and ESP-IDF
- used libraries:
- jirutka/GxEPD2_4G
- Arduino display lib for SPI e-inks with 2-bit grayscale
- fork with support for GDEM102T91
- pngle – stream-based portable PNG decoder
- PubSubClient – not so good MQTT client for Arduino
- ArduinoJson – JSON (de)serializer for Arduino/C++
- jirutka/GxEPD2_4G
Firmware
Monitoring

Source: ChatGPT 5 (DALL-E 3)
{
"ts": 1761483972,
"wakeTs": 1761483960,
"rstTs": 1760803498,
"rstRsn": "SW",
"nextWakeTs": 1761494760,
"awake": 2336,
"chip": "ESP32-D0WD-V3",
"fw": { "ver": "0.2.0", "size": 1018608, "freeSpace": 1310720 },
"disp": { "w": 480, "h": 800, "clr": "4g" },
"heap": { "total": 273172, "free": 180408, "minFree": 168848, "maxAlloc": 110580 },
"net": {
"mac": "D4:8C:49:CA:FF:EE",
"ipv4": { "addr": "192.168.123.42", "mask": 24, "gw": "192.168.123.1" },
"dns": [ "192.168.123.1" ],
"iface": "wlan",
"ssid": "fel-XXX",
"bssid": "08:96:AD:CA:FF:EE",
"chan": 1,
"rssi": -72
},
"battVolt": 4.22,
"battPct": 100
}Telemetry from door signs

Grafana

Grafana

Grafana

Grafana

Grafana
Fuckups Challenges
- ESP brownout
- RTC on ESP32 is inaccurate
- 5 V over PoE wasn’t enough → 7 V
- WiFi fast scan
- PubSubClient doesn’t support QoS ≥1

Why not “Živý obraz”?
We have a specialised use case with different requirements.
Also…
- firmware code-quality 🤢
- custom image format 🤨
- no support for observability (telemetry, remote logging)
- server is closed-source(?)


Bill of Material
- ESP board ESPink v2 (with IPEX) by LaskaKit.cz
- 10.2" e-ink display GDEM102T91
- (LiPol battery 10 000 mAh)
- antenna 3dB 2.4GHz with IPEX
- microswitch MSW-21
- capacitor 330uF/6.3V
- screws and dowels
- 3D printing filament for our custom case
| Item |
|---|
| ESP board ESPink v2 by LaskaKit.cz |
| 10.2" e-ink display GDEM102T91 |
| (LiPol battery 10 000 mAh) |
| microswitch MSW-21 |
| capacitor 330uF/6.3V |
| screws and dowels |
| 3D printing filament |
Bill of Material
| Item | Price (CZK) |
|---|---|
| ESP board ESPink v2 by LaskaKit.cz | 398 |
| 10.2" e-ink display GDEM102T91 | 2 020* |
| (LiPol battery 10 000 mAh) | 230* |
| microswitch MSW-21 | 6.5 |
| capacitor 330uF/6.3V | 1.6 |
| screws and dowels | 7.4 |
| 3D printing filament (253 g) | 84 |
| Total | 2748 |
What next?
- optimise WiFi – full scan only on first connection
- replace PubSubClient
- cache logs in Flash memory
- publish 3D models for the frame
- publish firmware
- deploy on more faculties, universities…?

Q&A
Source: ChatGPT 4 (DALL-E 2) trained on art stolen from the Internet
Electronic door signs
By Jakub J.
Electronic door signs
- 22