Remember those old website guestbooks—where you’d scribble a note to the webmaster and it’d proudly show up on the homepage? It sounds risky now, but back in the early naive days of the internet, it was a badge of honor for any blog.
I got hit by a wave of nostalgia (and I happened to have a thermal printer lying around), so I thought: why not bring the guestbook into the real world? What if anyone visiting my site could send me a message that pops out on a little slip of paper right on my desk?

Interfacing with the printer
Thermal printers are usually compatible with ESC/POS Protocol and this was the chosen method to interface with it. Since my printer does not have an official Linux driver, I am using the python-escpos library.
The first step, is to identify your Vendor ID, Product ID, Input Enable, and Output Enable values. Using lsusb -vvv
you can get that information:
Bus 001 Device 010: ID 6868:0200 gxmc # VendorID:ProductId
Device Descriptor:
...
idVendor 0x6868
idProduct 0x0200
...
Configuration Descriptor:
...
Interface Descriptor:
...
Endpoint Descriptor:
bEndpointAddress 0x03 EP 3 OUT
...
Endpoint Descriptor:
...
bEndpointAddress 0x81 EP 1 IN
These constants can be used to initialize escpos configuration. I am using a generic profile that is closer to my printer’s specification (paper size, resolution and capabilities).
from escpos.printer import Usb
printer = Usb(0x6868, 0x0200, in_ep=0x81, out_ep=0x03, profile="POS-5890")
Probably you are going to get a permission error the first time you print. This happens because udev
restricts access to USB devices by default.
Error: Device not found (Unable to open USB printer on (26728, 512): [Errno 13] Access denied (insufficient permissions))
To fix that, you can allow your users to directly access the printer by creating an udev
rule. Replace idVendor
and idProduct
with your printer’s constants.
$ # create a new rules file in udev
$ echo 'SUBSYSTEMS=="usb", ATTRS{idVendor}=="6868", ATTRS{idProduct}=="0200", GROUP="users", MODE="0666"' > /etc/udev/rules.d/50-printer.rules
$ # reload rules
$ udevadm control --reload-rules && udevadm trigger
Now your Thermal Guestbook can actually print!
Bringing the printer to the web
With a newborn at home Aider is what keeps my hobby alive. Aider is an AI pair programming tool and it was used to write more than 50% of the application code. The app has three components: the frontend, webserver, and worker.
The frontend is a simple HTML, CSS, and Vanilla JS page. The web API is implemented with FastAPI and it also serves the frontend. Every print request is added to a MQTT queue that is listened by the worker. Messages are saved in a SQLite database “for archaeological reasons”.
This webserver is running in a personal computer and it is accessible on the internet via Cloudflare Tunnels .

So what happened?
I posted the link to the printer (or fax reborn, as my wife dubbed it) and waited to see what happened. The results were surprising. After almost 100 messages, contrary to every expectation, most messages were fun, thoughtful and heartwarming. Notes from old friends, people that I am not in touch anymore, hacking attempts from colleagues, or just strangers sending messages.

No Title

Morning at the beach.

Hello world!

It started!

Bayes' theorem
P(A|B) = P(B | A) . P(A) / P(B)
{{7*8}}
Shrek (x 40)
Shrek
Shrek
Wanna leave your mark? Sign the guestbook at https://printer.tncardoso.com/ or peek at the code on GitHub .