Skip to content

vycdev/thermal-printer-scripts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Thermal Printer Scripts

A collection of small Python scripts that render and print 384px-wide receipts on a Phomemo / DP-S01–class BLE thermal printer. Each script fetches or generates something, lays it out as a 1-bit "card," and sends it to the printer over Bluetooth (or USB).

Everything shares one tiny toolkit (print_common.py) and a common set of CLI flags, so they all behave the same way.


How it works

  • print_common.py — the shared toolkit. A Card builder lays out content top-down (title, heading, line, para, kv, divider, image, footer) onto a 384px canvas, then finish() crops, frames, pads (top/bottom feed so the printer doesn't clip edges), and prints it. Also provides get_json / get_bytes (HTTP) and fit_dither (decode + scale + Floyd–Steinberg dither any image to 1-bit).
  • s1_print.py — print dispatcher; picks the transport.
  • direct_s1_ble_print.py / direct_s1_usb_print.py — the BLE / USB transports. print_s1_ble.py, s1_ble_console.py, ble_probe.py are pairing and diagnostic helpers.
  • toy_thermal_printer.py, usb_camera_verify.py, make_gradient_test.py, sitecustomize.py — utilities and test rigs.
  • s01_printer_config.json — printer identity / connection config.

Common flags

Almost every *_print.py accepts:

Flag Meaning
--no-print render the PNG only; don't send to the printer
--out PATH where to write the PNG
--darkness 1-5 print darkness (default 3)
--bottom-feed N blank feed at the bottom (default 24)

Generators take a --seed (printed on the card) so any result can be reproduced. Run any script with -h for its full options.

python pokemon_print.py --gen1            # random Gen-1 Pokémon card
python moon_print.py --no-print           # just render moon.png
python forecast_print.py --city Tokyo     # 7-day forecast with chart

Scripts by category

Daily & live data

Script Prints
calendar_month.py Month calendar grid; circles today
daylight_print.py Sunrise/sunset/solar-noon with a sun-arc diagram
moon_print.py Tonight's moon phase, drawn with the correct lit fraction
onthisday_print.py "On this day" historical events (Wikipedia) + photo
weather_print.py Local current weather
forecast_print.py 7-day forecast for any city, with a temp chart
airquality_print.py Air quality index + pollutants with a gauge
iss_print.py Current position of the ISS
earthquake_print.py Recent quakes (USGS) on a world dot-map
launches_print.py Upcoming rocket launches with countdowns
epic_print.py Full-disc Earth photo from NASA EPIC / DSCOVR
apod_print.py NASA Astronomy Picture of the Day
world_clock_print.py Analog local clock + time in major cities

Finance

Script Prints
crypto_print.py Crypto price + 7-day chart (CoinGecko)
forex_print.py Currency exchange rates + 30-day trend (ECB)

Reference & learning

Script Prints
word_of_day_print.py Word of the day with pronunciation & definitions
element_print.py Periodic-table element tile + properties
quote_print.py Inspirational quote, typeset
wiki_print.py Random Wikipedia article summary
ascii_print.py ASCII table (printable chars, dec/hex)
roman_print.py Roman numeral converter + reference
multiplication_print.py Times-table grid

Fun content (web APIs)

Script Prints
meme_print.py Random meme (Reddit via meme-api)
dark_joke_print.py Dark-humour joke (JokeAPI)
joke_print.py Random two-line joke
insult_print.py Random insult (Evil Insult Generator)
facts_print.py "Did you know?" mix of fact/joke APIs
bored_print.py A random activity to beat boredom
cocktail_print.py Cocktail recipe + photo (TheCocktailDB)
meal_print.py Meal recipe + photo (TheMealDB)
pokemon_print.py Pokémon trading card (PokeAPI)
pokemon_item_print.py Live random Pokemon item from PokeAPI
anime_character_print.py Anime character card (MyAnimeList)
starwars_print.py Star Wars character dossier (SWAPI)
album_print.py Album card + cover art (iTunes)
met_print.py Met Museum artwork (open collection)
country_print.py Country facts + flag
cat_print.py Random cat photo
xkcd_print.py Random xkcd comic
fake_human_print.py "Dossier" for a GAN face that doesn't exist
randomuser_print.py Random fake person profile
hacker_news_print.py Top Hacker News stories
color_print.py Colour of the day: name, codes, dithered swatch
internet_story_print.py Internet story from a live story API or Gutendex
news_feed_print.py Continuous live RSS headline tape
x_following_feed_print.py Print only new tweets from watched X/Twitter RSS feeds

Personalised

Script Prints
numerology_print.py Name numerology (Destiny / Soul / Personality)
biorhythm_print.py Physical/emotional/intellectual cycle chart

Divination

Script Prints
tarot_print.py Tarot card draw
iching_print.py I Ching hexagram with changing lines
fortune_print.py A fortune

Puzzles & games

Script Prints
maze_print.py Maze (with optional solution)
sudoku_print.py Sudoku (with optional answer key)
wordsearch_print.py Themed word search (with answer key)
nonogram_print.py Picross puzzle (logic-verified unique solution)
magicsquare_print.py Magic square (rows/cols/diagonals sum equal)
bingo_print.py 75-ball bingo cards
trivia_print.py Multiple-choice trivia quiz + answer key
wheel_print.py Decision wheel — picks one of your options

Tabletop / RPG

Script Prints
dungeon_print.py Roguelike dungeon map
dnd_print.py Random D&D character (stats, race, class)
tavern_print.py Fantasy tavern (menu, patrons, rumour)
magicitem_print.py Random magic item / loot
superhero_print.py Silly superhero origin card
dispatch_print.py Fictional field dispatch / incident report
artifact_print.py Fictional recovered artifact museum label
book_pick_print.py Real book recommendation from Open Library
trail_report_print.py Generated trail report with elevation profile
seed_packet_print.py Fictional seed packet with growth profile
paper_digest_print.py Curated digest of real research papers
poem_print.py Short poem card from PoetryDB or fallback classics
arxiv_brief_print.py arXiv paper brief with fallback summaries
abstract_snapshot_print.py Paper abstract with text-derived pulse chart
etymology_snapshot_print.py Dictionary entry with origin and definition-length chart
focus_plan_print.py Generated focus plan with schedule timeline
micro_lesson_print.py Short factual lesson with quiz
decision_memo_print.py Generated decision memo with scored options
git_activity_print.py Live Git worktree and commit activity brief
repo_metrics_print.py Live repository file metrics and extension chart
process_snapshot_print.py Live Windows process snapshot with memory chart
python_env_print.py Live Python environment package inventory
event_log_print.py Live Windows event log brief with level chart
github_events_print.py Live GitHub public-events pulse
dog_card_print.py Live random dog photo card from Dog CEO
duck_card_print.py Live random duck photo card from Random-d.uk
fox_card_print.py Live random fox photo card from RandomFox
card_hand_print.py Live playing-card hand from Deck of Cards API
mtg_card_print.py Live random Magic card from Scryfall
rickmorty_print.py Live Rick and Morty character card
dnd_monster_print.py Live D&D monster card from 5e API
yugioh_card_print.py Live random Yu-Gi-Oh card from YGOPRODeck
random_anime_print.py Live random anime card from Jikan
random_manga_print.py Live random manga card from Jikan
space_crew_print.py Live people-in-space crew card

Generative art

Script Prints
cellular_print.py Wolfram elementary cellular automaton
life_print.py Conway's Game of Life, 2×2 evolution montage
fractal_print.py Mandelbrot / Julia set
attractor_print.py Clifford / de Jong strange attractor
hilbert_print.py Hilbert space-filling curve
dragon_print.py Heighway dragon curve
koch_print.py Koch snowflake
spirograph_print.py Hypotrochoid rosettes
truchet_print.py Truchet arc tiling
phyllotaxis_print.py Sunflower seed spiral (golden angle)
voronoi_print.py Voronoi tessellation
mandala_print.py N-fold symmetric mandala (colouring-book)
flowfield_print.py Particle flow field
tree_print.py Recursive fractal tree
dna_print.py DNA double helix from a random sequence
constellation_print.py Invented constellation + mythology
invaders_print.py Swarm of random symmetric pixel sprites
aquarium_print.py Little fish-tank scene
pcb_print.py Generative circuit-board art
metro_print.py Generative metro map of an invented city
sort_print.py Sorting-algorithm visualization

Music

Script Prints
chord_print.py Guitar chord diagram
piano_print.py Piano scale diagram

Novelty & utility

Script Prints
barcode_print.py Scannable Code 39 barcode
morse_print.py Message in Morse code + key
eyechart_print.py Snellen eye chart
boardingpass_print.py Fake boarding pass
habit_tracker_print.py Monthly habit tracker grid
binaryclock_print.py Current time as binary-coded decimal
paper_print.py Blank templates (graph / dots / lined / staff / iso)
photo_print.py Print any image file (dithered)
map_print.py Map of a location
terrain_map_print.py Terrain / topographic map

Dev dashboards

Script Prints
github_print.py GitHub user stats
repo_print.py GitHub repository stats
claude_session_print.py Claude Code session summary
codex_status_print.py Codex status
neofetch_print.py System info, neofetch-style
terminal_print.py Real command output or simulated terminal transcript
live_stream_print.py Continuous live Wikimedia edit stream tape

Setup

python -m venv .venv
.venv\Scripts\activate           # Windows
pip install pillow bleak         # Pillow for rendering, bleak for BLE

Configure your printer target with S1_BLUETOOTH_TARGET or pass --bluetooth; S1_BLUETOOTH_ADDRESS can provide an optional fallback BLE address. The scripts also accept S1_TRANSPORT / PRINT_TRANSPORT to force a transport.

Writing a new script

from print_common import ROOT, Card, fit_dither, get_json, get_bytes

data = get_json("https://api.example.com/thing")
card = Card()
card.title("MY THING")
card.image(fit_dither(get_bytes(data["image"]), card.inner_w, 320))
card.para(data["text"])
card.footer("example.com")
card.finish(ROOT / "thing.png", do_print=True)

Card handles wrapping, dithering, the border, and the top/bottom feed so the printer doesn't clip the edges.


Docker GP-58 USB printer API

This repo also includes a small Linux HTTP sidecar for GP-58 / ESC-POS-style USB thermal printers that appear as /dev/usb/lp0.

The API is intentionally narrow: it owns the raw printer device and exposes only health checks plus text/random/image print endpoints. This is useful when an agent or another container should print without getting direct access to the USB device.

Run with Docker Compose

docker compose -f docker-compose.example.yml up --build

The example maps the host USB printer device class into the container:

volumes:
  - /dev/usb:/dev/usb
device_cgroup_rules:
  - "c 180:* rwm"
group_add:
  - "7"

On many Linux hosts /dev/usb/lp0 is owned by root:lp with group id 7, so group_add: ["7"] lets the non-root container user write to the printer.

For standalone local testing, uncomment the loopback-only port mapping in the compose file and call:

curl http://127.0.0.1:8787/health
curl -X POST http://127.0.0.1:8787/print/text \
  -H 'Content-Type: application/json' \
  -d '{"title":"Hermes","text":"hello from the tiny printer","dry_run":true}'

Remove "dry_run": true to actually print.

Client helper

thermal_printer_client.py is a small stdlib-only client for the HTTP sidecar. The Docker image installs it as thermal-printer, and Hermes can install or copy the same file as /opt/data/bin/thermal-printer.

thermal-printer health
thermal-printer text --dry-run --title Hermes "hello from Hermes"
thermal-printer random
thermal-printer image card.png --dry-run

By default the client calls http://127.0.0.1:8787. Set THERMAL_PRINTER_API_URL=http://thermal-printer:8787 when calling it from another container on the same Docker network.

Presence guard

The API can refuse real prints unless another machine is reachable by ICMP ping. This is useful for agents that should not print while you are away from your computer. Dry-runs still work.

environment:
  THERMAL_PRINTER_REQUIRE_PRESENCE: "1"
  THERMAL_PRINTER_PRESENCE_HOST: "<TAILSCALE_DESKTOP_IP>"
  THERMAL_PRINTER_PRESENCE_TIMEOUT: "2"

Check the configured guard with:

thermal-printer presence

If the guard is enabled and the target is not reachable, real print requests return HTTP 409 Conflict and nothing is written to the printer.

API endpoints

  • GET /health returns printer device status and presence guard config without pinging.
  • GET /presence pings the configured presence target and returns guard status.
  • POST /print/text prints text with optional title, footer, and feed_lines.
  • POST /print/random prints a short built-in random message, or a supplied text.
  • POST /print/image prints an image using ESC/POS raster mode from either a container-local path or an image_base64 body.

Example internal call from another container on the same Docker network:

curl -X POST http://thermal-printer:8787/print/random \
  -H 'Content-Type: application/json' \
  -d '{}'

Direct device CLI

Inside the container or on a Linux host with direct access to /dev/usb/lp0:

python gp58_print.py status
python gp58_print.py text "hello" --title Hermes --dry-run
python gp58_print.py random
python gp58_print.py image card.png

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors