From d95b07706f3faf6d41375ce677d4721088f91e64 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 3 Jun 2026 23:58:15 +0000 Subject: [PATCH 1/2] Pin pyusb (and pyserial) explicitly in pi-clients requirements python-escpos lists pyusb as an optional install extra, so a vanilla pip install -r requirements.txt left the USB printer backend missing the underlying library and every print attempt failed at runtime with 'Printing with USB connection requires a usb library to be installed'. pyserial gets the same treatment for the serial backend, so both paths work out of the box. --- pi-clients/requirements.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pi-clients/requirements.txt b/pi-clients/requirements.txt index 8723fa2..993345f 100644 --- a/pi-clients/requirements.txt +++ b/pi-clients/requirements.txt @@ -1,5 +1,10 @@ supabase>=2.5.0,<3 pydantic>=2.6,<3 python-escpos>=3.0,<4 +# python-escpos lists pyusb as an optional dep; without it the USB backend +# fails at runtime with "Printing with USB connection requires a usb library +# to be installed". Pin it explicitly so installs don't drift. +pyusb>=1.2,<2 +pyserial>=3.5,<4 evdev>=1.6,<2 ; sys_platform == "linux" python-dotenv>=1.0,<2 From 5d64d3f5ac41b6d0334444ca808b1dec8e5f28ff Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 5 Jun 2026 00:22:32 +0000 Subject: [PATCH 2/2] Prettier ticket rendering: double-width title, bold double-height date MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit format='ticket' now prints the title at double-width + double-height so it reads at arm's length on the fridge, and the subtitle (date/time) gets bold + double-height so it stands out without burning two paper rows. list / daily / custom keep the slim layout that fits more lines per inch — the shopping list format was already perfect. --- pi-clients/printer/render.py | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/pi-clients/printer/render.py b/pi-clients/printer/render.py index 92233c6..9b318f5 100644 --- a/pi-clients/printer/render.py +++ b/pi-clients/printer/render.py @@ -29,14 +29,33 @@ def render(printer: _EscposLike, payload: PrintPayload, width: int = 32) -> None if width < 16: width = 16 # paranoia: don't divide by zero in layout math - # ---- title (double height + bold, centered) ------------------- - printer.set(align="center", bold=True, double_height=True, double_width=False) - printer.text(_truncate(payload.title, width) + "\n") - printer.set(align="center", bold=False, double_height=False, double_width=False) - - # ---- subtitle (centered, normal) ------------------------------ + is_ticket = payload.format == "ticket" + + # ---- title ----------------------------------------------------- + # Tickets get a chunkier title (double width + double height) so they + # read at arm's length on the fridge. Lists keep the slimmer look that + # fits more lines per inch of paper. + if is_ticket: + printer.set(align="center", bold=True, double_height=True, double_width=True) + # Double-width chars take 2 cols, so the practical width halves. + printer.text(_truncate(payload.title, width // 2) + "\n") + else: + printer.set(align="center", bold=True, double_height=True, double_width=False) + printer.text(_truncate(payload.title, width) + "\n") + + # ---- subtitle -------------------------------------------------- if payload.subtitle: - printer.text(_truncate(payload.subtitle, width) + "\n") + if is_ticket: + # Bold + double-height (not double-width) — bigger date without + # eating two paper rows of vertical space. + printer.set(align="center", bold=True, double_height=True, double_width=False) + printer.text(_truncate(payload.subtitle, width) + "\n") + else: + printer.set(align="center", bold=False, double_height=False, double_width=False) + printer.text(_truncate(payload.subtitle, width) + "\n") + + # Reset to plain and draw the divider. + printer.set(align="center", bold=False, double_height=False, double_width=False) printer.text("-" * width + "\n") # ---- body lines ----------------------------------------------