da8f557219
GPU Scheduler (gpu.sethpc.xyz): - Live dashboard with 4 GPUs, training monitor, loss sparklines - Preset-based job scheduler with 3 triggers (time, finish_training, cost) - Model selection per GPU, pipeline configuration - Tool self-play and training pipeline types - Behind Google OAuth, live-refresh without page reload Tool Architecture (14 tools): - 3 new tools: world.nearby_entities, memory.read, memory.write - 7 script.* tools: write, validate, execute, read, list, delete, schedule - ScriptManager: full mcfunction datapack CRUD with RCON validation - Training data: 1,430 tool examples (up from 1,159) Plugin Deployment (paper-ai-25567): - WorldGuard 7.0.12, CoreProtect CE 23.1, EssentialsX 2.21.2, Vault 1.7.3 - Fresh greenfield world reset - 104 RCON-validated plugin training examples Event Dispatcher: - Watches server log for deaths, joins, advancements, PvP kills - Configurable trigger probability and cooldowns per event type - Deployed to dev server, fires god_system prompts on events - 21 event-response training examples Training Infrastructure: - train_lora.py: --save-steps 50, --resume from checkpoint - run_training.sh: stops Ollama, activates conda, restarts after - Passwordless sudo for ollama services on steel141 - Dev server added to MCSManager with autoStart Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
203 lines
7.2 KiB
Markdown
Executable File
203 lines
7.2 KiB
Markdown
Executable File
# POS_PRINT.md — Printing to the Epson TM-m30
|
||
|
||
Quick-reference for any agent or script that needs to print arbitrary content on the receipt printer.
|
||
|
||
USER may explicitly use this file in lieu of a formal request to print.
|
||
|
||
## Printer Details
|
||
|
||
Exact model reference: `https://www.amazon.com/dp/B01GO08MW2`
|
||
|
||
### Core
|
||
|
||
| Field | Value |
|
||
|---|---|
|
||
| Model | Epson TM-m30 |
|
||
| Print method | Thermal |
|
||
| Print speed | 200 mm/second |
|
||
| Print resolution | 203 dpi |
|
||
| Print direction | Vertical and horizontal |
|
||
| Protocol used here | ESC/POS over raw TCP |
|
||
| IP | `192.168.0.137` |
|
||
| Port | `9100` |
|
||
| Profile | `default` (python-escpos) |
|
||
|
||
### Fonts and characters
|
||
|
||
| Field | Value |
|
||
|---|---|
|
||
| Fonts / columns | Font A: 12 x 24, 48 cpl (default); Font B: 10 x 24, 57 cpl; Font C: 9 x 17, 64 cpl |
|
||
| Character size | Font A: 1.25 x 3.00 mm; Font B: 1.13 x 3.00 mm; Font C: 0.88 x 2.13 mm |
|
||
| Character set | 95 alphanumeric, 18 international, 128 x 43 |
|
||
|
||
### Barcode and 2D symbols
|
||
|
||
| Field | Value |
|
||
|---|---|
|
||
| Barcode | UPC-A, UPC-E, JAN8 / EAN8, JAN13 / EAN13, Code39, Code93, Code128, ITF, CODABAR (NW-7), GS1-128, GS1 DataBar |
|
||
| 2D symbols | PDF417, QR Code, MaxiCode, Data Matrix, Aztec Code, 2D GS1 DataBar, Composite Symbology |
|
||
|
||
### Media handling
|
||
|
||
| Field | Value |
|
||
|---|---|
|
||
| Type | Thermal roll paper |
|
||
| Paper feed method | Friction feed |
|
||
| Width | 3.12 in / 79.5 mm |
|
||
| Paper loading | Drop-in |
|
||
| Roll diameter (max) | 3.27 in / 83 mm |
|
||
| Core diameter (min) | 0.71 in / 18 mm |
|
||
| Paper guide | Yes |
|
||
| Auto cutter | Yes |
|
||
|
||
### Connectivity
|
||
|
||
| Field | Value |
|
||
|---|---|
|
||
| Ethernet model | Built-in USB + Ethernet 10/100Base-T/TX |
|
||
| Bluetooth model | Built-in USB + Bluetooth 3.0 (EDR supported) + Ethernet 10/100Base-T/TX |
|
||
| Wi-Fi model | Built-in USB + 802.11b/g/n (2.4 GHz) and 802.11a/n (5 GHz) + Ethernet 10/100Base-T/TX |
|
||
| Wireless security mode | WEP, WPA, WPA2 Personal/Enterprise |
|
||
| Supported mobile OS | iOS, Android, Windows (Store Apps) |
|
||
| Easy setting | SimpleAP, TM Utility, NFC, QR Code |
|
||
|
||
### General
|
||
|
||
| Field | Value |
|
||
|---|---|
|
||
| Printer reliability | 15 million printing lines |
|
||
| Auto cutter reliability | 1.5 million cuts |
|
||
| NV bit image memory | 12 KB (max) |
|
||
| NV graphics | 384 KB (max) |
|
||
| Receive buffer | 4 KB or 45 bytes |
|
||
| Printer drivers | ePOS-Print SDK, Windows Driver (APD), OPOS, OPOS.NET, JavaPOS (Win), JavaPOS (Linux), TM Virtual Port Driver, CUPS Driver (Linux), Mac Driver |
|
||
| Software | TM Utility (iOS, Android), TM-m30 Utility (Windows Desktop), EpsonNet Config (Win, Mac), TM Bluetooth Connector, Deployment Tool, Monitoring Tool |
|
||
| Audible alert | Optional external buzzer |
|
||
| LED indicators | Blue LED = Power, Orange LED = Error and/or Paper Out |
|
||
| Sensors | Paper End, Cover Open |
|
||
| D.K.D. function | Yes |
|
||
| Power consumption | Approx. 1.5 A (mean) |
|
||
| Power source | Adapter C, Adapter RA (printer powers tablet SKU only) |
|
||
| Power saving | Yes |
|
||
| Temperature | 5 C to 45 C |
|
||
| Relative humidity | 10 to 90% |
|
||
| Acoustic noise level | 55 dB |
|
||
| Standards and approvals | EMI FCC Class A, CAN ICES-3(A)/NMB-3(A), UL60950-1/CSA C22.2 No.60950-1 |
|
||
| Dimensions (W x D x H) | 5 x 5 x 5 in (127 x 127 x 127 mm) |
|
||
| Weight | 2.64 lb / 1200 g |
|
||
| Color | Epson Black, Epson Ultra White |
|
||
| Options | Mounting brackets, external buzzer |
|
||
|
||
## Minimal Print Example
|
||
|
||
```python
|
||
import socket
|
||
from escpos.printer import Dummy
|
||
|
||
PRINTER_IP = "192.168.0.137"
|
||
PRINTER_PORT = 9100
|
||
COLS = 57 # Font B on 80mm paper
|
||
|
||
# 1. Build the receipt with a Dummy (in-memory) printer
|
||
p = Dummy(profile="default")
|
||
p.set(font='b', align='center', bold=True)
|
||
p.text("Hello from the POS printer!\n")
|
||
p.set(font='b', align='left', bold=False)
|
||
p.text("This is normal left-aligned text.\n")
|
||
p.cut()
|
||
|
||
# 2. Send raw bytes over TCP
|
||
with socket.create_connection((PRINTER_IP, PRINTER_PORT), timeout=10) as sock:
|
||
sock.sendall(p.output)
|
||
```
|
||
|
||
**Dependencies:** `pip3 install python-escpos`
|
||
(plus `qrcode` if you use QR codes)
|
||
|
||
## How It Works
|
||
|
||
The pattern is always the same — **build bytes, then send bytes**:
|
||
|
||
1. **Build** — Instantiate `escpos.printer.Dummy`. Call formatting/content methods on it. All ESC/POS command bytes accumulate in `p.output`.
|
||
2. **Send** — Open a raw TCP socket to `192.168.0.137:9100` and `sendall(p.output)`. The printer interprets the byte stream natively. No driver, no CUPS, no PDF.
|
||
|
||
## Formatting Reference
|
||
|
||
All formatting is done via `p.set()`. Always pass `font='b'` (Font B gives 57 columns on 80 mm paper; Font A gives fewer).
|
||
|
||
```python
|
||
# Bold, centered header
|
||
p.set(font='b', align='center', bold=True)
|
||
p.text("TITLE\n")
|
||
|
||
# Normal left-aligned body text
|
||
p.set(font='b', align='left', bold=False)
|
||
p.text("Body text here.\n")
|
||
|
||
# Right-aligned
|
||
p.set(font='b', align='right', bold=False)
|
||
p.text("Right side\n")
|
||
```
|
||
|
||
### Available `p.set()` kwargs
|
||
|
||
| Kwarg | Values | Notes |
|
||
|---|---|---|
|
||
| `font` | `'a'`, `'b'` | Always use `'b'` for 57-col width |
|
||
| `align` | `'left'`, `'center'`, `'right'` | |
|
||
| `bold` | `True` / `False` | |
|
||
| `underline` | `0`, `1`, `2` | 0=off, 1=single, 2=double |
|
||
| `width` | `1`–`8` | Character width multiplier |
|
||
| `height` | `1`–`8` | Character height multiplier |
|
||
| `density` | `0`–`8` | Print density |
|
||
| `invert` | `True` / `False` | White on black |
|
||
| `smooth` | `True` / `False` | Smoothing mode |
|
||
| `flip` | `True` / `False` | Upside-down printing |
|
||
|
||
### Content Methods
|
||
|
||
```python
|
||
p.text("Plain text with newlines\n") # Text (wrap manually at COLS)
|
||
p.qr("https://example.com", native=True, size=3) # QR code (native=True uses printer HW)
|
||
p.image(pil_image) # PIL Image object
|
||
p.barcode("123456", "EAN13") # Barcode
|
||
p.cut() # Paper cut (always do this at the end)
|
||
```
|
||
|
||
### Separators
|
||
|
||
```python
|
||
COLS = 57
|
||
p.text("=" * COLS + "\n") # Thick separator
|
||
p.text("-" * COLS + "\n") # Thin separator
|
||
```
|
||
|
||
## Reusable Send Function
|
||
|
||
```python
|
||
import socket
|
||
|
||
def send_to_printer(raw_bytes, ip="192.168.0.137", port=9100):
|
||
"""Send raw ESC/POS bytes to the TM-m30 over TCP."""
|
||
with socket.create_connection((ip, port), timeout=10) as sock:
|
||
sock.sendall(raw_bytes)
|
||
```
|
||
|
||
## Troubleshooting
|
||
|
||
- **Printer unreachable:** `192.168.0.137` can have intermittent ARP issues from some CTs. Ping first or retry.
|
||
- **Garbled output:** You probably mixed Font A and Font B column math. Stick to Font B (`font='b'`) and `COLS = 57`.
|
||
- **No cut at end:** Always call `p.cut()` as the last content method. Without it the receipt hangs out of the printer.
|
||
- **QR code not printing:** Ensure `native=True` is passed to `p.qr()`. The TM-m30 supports hardware QR generation. Also needs the `qrcode` pip package installed.
|
||
|
||
## Daily Briefing Project
|
||
|
||
For printing a full daily news briefing (FreshRSS headlines summarized by Ollama, weather, ZFS status, Grafana metrics, market data, Reddit top post, QR codes), see:
|
||
|
||
- **Project:** `/root/bin/POS-Automation/`
|
||
- **Main script:** `/root/bin/POS-Automation/pos_briefing.py`
|
||
- **Context:** `/root/bin/POS-Automation/CONTEXT.md`
|
||
- **Gitea:** `https://git.sethpc.xyz/Seth/POS-Automation`
|
||
|
||
That project's `build_receipt()` function (line 356) is the most complete example of a multi-section ESC/POS receipt with headers, dashboard data, QR codes, and article summaries. Fork it or import its patterns if you need structured receipt layouts.
|