Metadata-Version: 2.4
Name: py-star-tsp
Version: 2.0.0
Summary: Python SDK for Star TSP100 Graphic Mode thermal printers
Author-email: Pavel Kim <hello@pavelkim.com>
License: GPL-3.0-only
Project-URL: Homepage, https://github.com/printer-stream/py-star-tsp
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Operating System :: OS Independent
Classifier: Topic :: Printing
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pyusb>=1.3.0
Requires-Dist: Pillow>=12.0.0
Dynamic: license-file

# py-star-tsp

[![PyPI version](https://img.shields.io/pypi/v/py-star-tsp)](https://pypi.org/project/py-star-tsp/)
[![Python versions](https://img.shields.io/pypi/pyversions/py-star-tsp)](https://pypi.org/project/py-star-tsp/)
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Build](https://github.com/printer-stream/py-star-tsp/actions/workflows/release.yml/badge.svg)](https://github.com/printer-stream/py-star-tsp/actions/workflows/release.yml)
[![PyPI downloads](https://img.shields.io/pypi/dm/py-star-tsp)](https://pypi.org/project/py-star-tsp/)

![Printing with py-star-tsp](doc/long_demo_print_loop.gif)

Python SDK for **Star** thermal printers operating in **Graphic Mode** over USB.

Following the **STAR Graphic Mode Command Specifications Rev. 2.31**.

## Supported Models

| Model        | Interface       | Tested |
| ---          | ---             | ---    |
| TSP100U      | USB             | -      |
| TSP100PU     | USB + Parallel  | -      |
| TSP100GT     | USB + Ethernet  | -      |
| TSP100LAN    | Ethernet        | -      |
| TSP100IIU    | USB             | Y      |
| TSP100IIIW   | USB + Wi-Fi     | -      |
| TSP100IIILAN | USB + Ethernet  | -      |
| TSP100IIIBI  | USB + Bluetooth | -      |
| TSP100IIIU   | USB             | -      |


## Installation

```bash
pip install py-star-tsp
```

## Usage examples

### Reference page

README: [examples/README.md](https://github.com/printer-stream/py-star-tsp/tree/master/examples)

### Regular usage

```python
import datetime
import py_star_tsp

with py_star_tsp.StarTSP100() as printer:
    # Changing print speed to slow
    printer.print_speed = 2

    # Changing print quality to high
    printer.raster_print_quality = 2

    # Device discovery
    printer.find_device()

    # Preparing timestamp label
    timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    # Preparing content
    title = "Before Flying Circus"
    paragraph = """Jones and Palin met at Oxford University, where they performed togethe
r with the Oxford Revue. Chapman and Cleese met at Cambridge Universit
y. Idle was also at Cambridge, but started a year after Chapman and Cl
eese. Cleese met Gilliam in New York City while on tour with the Cambr
idge University Footlights revue Cambridge Circus (originally entitled
 A Clump of Plinths). Chapman, Cleese, and Idle were members of the Fo
otlights, which at that time also included the future Goodies (Tim Bro
oke-Taylor, Bill Oddie, and Graeme Garden), and Jonathan Lynn (co-writ
er of Yes Minister and Yes, Prime Minister).[12] During Idle's preside
ncy of the club, feminist writer Germaine Greer and broadcaster Clive 
James were members. Recordings of Footlights' revues (called "Smokers"
) at Pembroke College include sketches and performances by Cleese and 
Idle, which, along with tapes of Idle's performances in some of the dr
ama society's theatrical productions, are kept in the archives of the 
Pembroke Players.
    """

    # Adding content to the printing "queue"
    printer.add_text(timestamp, font_size=30, invert=True)
    printer.add_bar(width=0, height=15)
    printer.add_image(py_star_tsp.KITTENS_SPINNING)
    printer.add_bar(width=0, height=15)
    printer.add_text(title, font_size=50)
    printer.add_bar(width=0, height=15)
    printer.add_text(paragraph, font_size=20)
    printer.add_image(py_star_tsp.KITTENS_SPINNING, invert=True)

    # Exporting a preview
    printer.save_rendered("/tmp/rendered_example.bmp")

    # Printing out
    printer.print()
```

### Print separately prepared raster

```python
import datetime
import PIL

import py_star_tsp

with py_star_tsp.StarTSP100() as printer:
    # Changing print quality to high
    printer.raster_print_quality = 2

    # Device discovery
    printer.find_device()

    # Create your own image
    your_image = Image.new("L", (100, 200), color=255)
    draw = ImageDraw.Draw(your_image)
    draw.multiline_text((10, 10), "HELLO THERE.", fill=0)

    # Initialise RasterImage object
    raster_image = RasterImage(image=your_image)

    # Add RasterImage object to the printing "queue"
    printer.add_raster(raster=raster_image)

    # Exporting a preview
    printer.save_rendered("/tmp/rendered_example.bmp")

    # Printing out
    printer.print()
```

## Linux USB Access (udev rule)

By default, USB devices are accessible only to `root`. Add the following udev rule to grant access to all users in the `plugdev` group:

```
# /etc/udev/rules.d/99-star-tsp100.rules
SUBSYSTEM=="usb", ATTRS{idVendor}=="0519", MODE="0666", GROUP="plugdev"
```

Reload rules and reconnect the printer:

```bash
sudo udevadm control --reload-rules
sudo udevadm trigger
```

Add your user to the `plugdev` group if necessary:

```bash
sudo usermod -aG plugdev $USER
```

## Font Discovery and Fallback

The text renderer automatically scans standard OS directories for
`.ttf` and `.otf` fonts:

| OS | Search paths |
|---|---|
| Linux | `/usr/share/fonts`, `/usr/local/share/fonts`, `~/.local/share/fonts`, `~/.fonts` |
| macOS | `/System/Library/Fonts`, `/Library/Fonts`, `~/Library/Fonts` |
| Windows | `%WINDIR%\Fonts` |

You can also set the `FONTPATH` environment variable to add custom directories
(separated by `os.pathsep`).

### Fallback font order

When no specific font is requested, the following are tried in order:

1. DejaVu Sans Mono
2. Liberation Mono
3. FreeMono
4. Arial
5. Consolas
6. Courier New

If **no TrueType/OpenType fonts are found at all**, Pillow's built-in
bitmap font is used.  This bitmap font does **not** support sizing,
bold, italic, or underline — a warning is logged.

### Font source packages

Install these Python/system packages to ensure fonts are available:

- **matplotlib** — ships DejaVu Sans / DejaVu Sans Mono
- **fonttools** — useful for font metadata inspection
- **fonts-dejavu** (Debian/Ubuntu) / **dejavu-sans-mono-fonts** (Fedora/Rocky) — DejaVu family
- **fonts-liberation** (Debian/Ubuntu) / **liberation-mono-fonts** (Fedora/Rocky) — Liberation family


## Preview / Export

You can save the queued raster output to an image file before sending it to the printer.

```python
from py_star_tsp import StarTSP

printer = StarTSP()
printer.add_text("Preview me")
printer.add_bar(width=576, height=8)

printer.save_rendered("preview.bmp")
printer.save_rendered("preview.jpg", quality=95)

image = printer.render_image()
print(image.size)
```

Use BMP if you want an exact 1-bit preview of what will be sent to the printer. JPEG is supported too, but it is exported as grayscale because JPEG does not support 1-bit images.

## ESC/POS Compatibility

More examples: [README.md](/examples/README.md)

ESC/POS Command Reference: [download4.epson.biz](https://download4.epson.biz/sec_pubs/pos/reference_en/escpos/)

The general approach in `py-star-tsp` to emulate ESC/POS for Star TSP100 printer is introduce a virtual ESC/POS compatible network server as a middleware. The conversion is done upon receiving the commands over TCP socket.

There is an emulation layer implemented as a separate module `py_star_tsp.escpos`. At this point very limited number of commands supported and tested.

You can use `python-escpos` to operate a Star TSP100 printer as if it had ESC/POS support.

Quick example of how to start a virtual print server:

```python
import asyncio

from py_star_tsp import StarTSP100
from py_star_tsp.escpos import PRESET_EPSON_TM_T88
from py_star_tsp.server import EscposServer

def on_print(raster_set):
    with StarTSP100() as printer:
        for block in raster_set.blocks:
            printer.add_raster(block)
        printer.print()

async def main():
    server = EscposServer(preset=preset, on_print=on_print)
    await server.start()

asyncio.run(main())
```

Quick example of how to print on Star TSP100 with `python-escpos`:

```python
from escpos.printer import Network

SERVER_HOST = "127.0.0.1"
SERVER_PORT = 9100

p = Network(SERVER_HOST, port=SERVER_PORT)
p.set_with_default()
p.set(align="center", bold=False)
p.text("Printing on Star TSP100\nwith py-star-tsp and python-escpos\n")
p.set(align="center", bold=False)
p.close()
```

## Licensing

* Kitten in the demos by Deni Sudibyo

## TODO

* 2d code implementation (barcode, qr, etc)
* Python version compatibility
* DONEISH: ESC/POS compatibility (very long term)
* DONE: Usage with external rendering (just printing ready to use raster)
* DONE: Turn demo to a reference sheet
* DONE: Generate a preview of what's rendered to be printed
