Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ and the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
## [Unreleased]

### Added
- **Print station** for the warehouse floor: a locked, print-only screen started with `Rotula.exe --station <folder, station.json or label>` (without a path it uses `%ProgramData%\Rotula\station.json`) or from **File > Open print station**. Labels show as large tiles with thumbnails and a search box; scanning a label's code opens it. Its questions are large fields that take keyboard-wedge scanner input: Enter or Tab moves to the next one, the last scan can print at once, and the label's own rules (required, length, pattern) are checked before anything is sent. Printing goes through the same print path as the Print dialog with the printer status check, and the result is shown in large plain words (ready, held back with the reason, printed and verified, not confirmed); the questions then reset for the next item, keeping the answers the station is told to keep. A `station.json` sets the labels and their scan codes, the printer of each label or a default, copy limits, whether the label's data may be printed, and an exit PIN stored only as a salted PBKDF2 hash (made with **File > Create print station PIN** or `Rotula.exe --station-pin`); five wrong PINs lock the PIN box for 30 seconds. Every setting is checked and a mistake is explained with the setting and line. See [docs/print-station.md](docs/print-station.md).
- **Printer status before and after printing** (ZPL `~HS`). Before each job Rotula asks the printer for its status and does not send while it reports it is out of labels, its printhead is open, the ribbon is out, it is paused, too hot, in diagnostics mode or its buffer is full; the Print dialog says which and what to do. After the job it waits (up to 30 seconds) until the printer reports it finished, then says "printed and verified", names a fault that appeared after the job (the labels still count as possibly printed, so no serial number is reused), or says it could not confirm. A printer that cannot answer never blocks printing. On by default for network printers and off for Windows printers, switchable in the Print dialog; "Check printer status" shows the decoded answer at any time. The MCP server has a matching `get_printer_status` tool.
- **A gallery of eight showcase labels** in the README (GS1-128 pallet, parcel, food, wine, lab specimen, asset tag, shelf tags with data merge, print conditions). Their `.rotula` files and the CSV data are in `docs/showcase`, and the pictures are rendered with Rotula's own PNG export by a test that only runs when `ROTULA_RENDER_SHOWCASE=1` is set.
- **Text fit for wrapped text** (Properties panel, Text fit): choose what a text block does when its text is longer than the box. "Shrink to fit" uses the largest font size, between a smallest and a largest size you set, at which all the text fits; "Grow height" adds lines, up to a limit you set, so all the text shows. With data merge every record gets the size or the lines its own text needs, the canvas shows the same size that prints, and "Do not warn" hides the does-not-fit warning when cutting the text off is what you want. Labels that do not use it are saved exactly as before; a label that does cannot be opened by older versions of Rotula.
Expand Down
21 changes: 21 additions & 0 deletions README.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Diséñala, previsualízala, combina tus datos e imprímela. Sin cuenta, sin nub
- [Etiquetas y rollos de la biblioteca](#etiquetas-y-rollos-de-la-biblioteca)
- [Fuentes de bases de datos](#fuentes-de-bases-de-datos)
- [Impresión](#impresión)
- [Puesto de impresión](#puesto-de-impresión)
- [Servidor MCP](#servidor-mcp)
- [Códigos de barras compatibles](#códigos-de-barras-compatibles)
- [Idiomas](#idiomas)
Expand Down Expand Up @@ -170,6 +171,7 @@ salida es determinista y en ASCII puro, así que puedes versionarla, compararla
| **Cobertura ZPL** | 222 comandos ZPL revisados uno por uno en una [página de cobertura generada](docs/zpl-coverage.md) (en inglés) |
| **Servidor MCP** | Un programa aparte que permite a los clientes compatibles con MCP diseñar y revisar etiquetas ([detalles](#servidor-mcp)) |
| **Impresión** | Cola de Windows (RAW, incluido USB) y puerto TCP 9100, detección de DPI y papel, perfiles de impresora, etiqueta de prueba, comprobación del estado de la impresora antes y después de cada trabajo |
| **Puesto de impresión** | Una pantalla bloqueada, solo para imprimir, pensada para el almacén: elige o escanea una etiqueta, responde a sus preguntas con un lector de códigos, imprime y lee la respuesta de la impresora en letra grande y palabras sencillas ([detalles](#puesto-de-impresión)) |
| **Resolución** | Convierte una etiqueta entre 203, 300 y 600 dpi conservando su tamaño físico |
| **Idiomas** | Español e inglés, con cambio en vivo |

Expand Down Expand Up @@ -392,6 +394,25 @@ Más información en [docs/printing.md](docs/printing.md) (en inglés).

---

## Puesto de impresión

Una pantalla solo para imprimir, para operarios, que se abre con `Rotula.exe --station <carpeta>` (o **Archivo > Abrir puesto de
impresión**). Muestra las etiquetas de una carpeta como mosaicos grandes, sin menús ni herramientas de diseño.

- **Elegir o escanear.** Toca un mosaico, escribe parte de su nombre o escanea el código que el puesto asigna a la etiqueta.
- **Pensado para lectores.** Las preguntas de la etiqueta son campos grandes; un lector de códigos de tipo teclado rellena uno y su
Intro o Tab pasa al siguiente. Con "imprimir al último escaneo" el último escaneo imprime en el acto. Antes se comprueban las
reglas de la propia etiqueta (obligatorio, longitud, patrón), y un escaneo rechazado se queda en su campo.
- **Resultado claro.** Lista, retenida (por ejemplo "el cabezal está abierto"), impresa y verificada, o sin confirmar, en letra
grande y palabras sencillas. Después las preguntas se vacían para la siguiente pieza; se pueden conservar las respuestas elegidas.
- **Bloqueado.** Para salir hace falta un PIN cuando se ha definido (solo se guarda un hash con sal). Las impresoras, los límites
de copias, la impresión de datos y el PIN vienen de un `station.json` junto a las etiquetas o en `%ProgramData%\Rotula`, así que
el puesto se puede configurar por directiva.

Más información en [docs/print-station.md](docs/print-station.md) (en inglés).

---

## Códigos de barras compatibles

Rotula escribe y lee **28 comandos ZPL de códigos de barras** (lineales, 2D, apilados y postales; la lista completa está en la [página de cobertura](docs/zpl-coverage.md)).
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Design it, preview it, merge your data, print it. No account, no cloud, no telem
- [Label stocks](#label-stocks)
- [Database sources](#database-sources)
- [Printing](#printing)
- [Print station](#print-station)
- [MCP server](#mcp-server)
- [Barcode support](#barcode-support)
- [Languages](#languages)
Expand Down Expand Up @@ -167,6 +168,7 @@ deterministic and plain ASCII, so you can version it, diff it or send it with an
| **ZPL coverage** | 222 ZPL commands tracked one by one on a [generated coverage page](docs/zpl-coverage.md) |
| **MCP server** | A separate program that lets MCP-capable clients design and check labels ([details](#mcp-server)) |
| **Printing** | Windows spooler (RAW, including USB) and TCP port 9100, DPI and paper detection, printer profiles, test label, printer status check before and after a job |
| **Print station** | A locked, print-only screen for the warehouse floor: pick or scan a label, answer its questions with a barcode scanner, print, and read the printer's answer in large plain words ([details](#print-station)) |
| **Resolution** | Convert a label between 203, 300 and 600 dpi while keeping its physical size |
| **Languages** | English and Spanish, switchable live |

Expand Down Expand Up @@ -383,6 +385,24 @@ More in [docs/printing.md](docs/printing.md).

---

## Print station

A print-only screen for operators, started with `Rotula.exe --station <folder>` (or **File > Open print station**). It shows
the labels of one folder as large tiles, with no menus and no design tools.

- **Pick or scan.** Tap a tile, type part of its name, or scan the code the station gives the label.
- **Scanner friendly.** The label's questions are large fields; a keyboard-wedge scanner fills one and its Enter or Tab moves to
the next. With "print on last scan" the last scan prints at once. The label's own rules (required, length, pattern) are
checked first, and a refused scan stays in its field.
- **Clear result.** Ready, held back (for example "the printhead is open"), printed and verified, or could not confirm, in
large plain words. The questions then reset for the next item; chosen answers can be kept.
- **Locked.** Leaving needs a PIN when one is set (stored only as a salted hash). Printers, copy limits, data printing and the
PIN come from a `station.json` next to the labels or in `%ProgramData%\Rotula`, so the station can be set up by policy.

More in [docs/print-station.md](docs/print-station.md).

---

## Barcode support

Rotula writes and reads **28 ZPL barcode commands** (linear, 2D, stacked and postal; the full list is on the [coverage page](docs/zpl-coverage.md)).
Expand Down
18 changes: 18 additions & 0 deletions docs/decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -539,3 +539,21 @@ emitted or validated, so a barcode invalid only on a record where it is hidden d
prints and PNG/JPEG/PDF; only the design canvas draws them dimmed (`includeNonPrinting`), and the Preview window shows the printed result. Lock is
enforced in `EditorCommands` (move, nudge, resize, rotate, align, distribute, delete, cut) and never touches ZPL; property edits stay allowed.
Condition fields are listed as merge placeholders so they can be mapped to columns. ZPL import never creates conditions or locks.

## Print station (Rotula.Files/Station, StationViewModel)

### One print path, a locked screen on top
The station is a separate window over the same services as the designer: it builds the printer target and profile through
`PrinterSettingsViewModel`, asks the label's questions through `PromptSet`, and prints through `IPrintService` with the status check on. So a
label prints the same from the station as from the Print dialog, and nothing in the print path knows about stations.

### The configuration is strict and the PIN is only a hash
`station.json` refuses unknown settings (`UnmappedMemberHandling.Disallow`), so a misspelt `maxCopies` is an error with its line, not a silently
unlimited station. The exit PIN is stored as `pbkdf2-sha256$<iterations>$<salt>$<hash>` (600,000 iterations, 16-byte salt) and checked with
`CryptographicOperations.FixedTimeEquals`, from the framework only. Five wrong PINs lock the box for 30 seconds. The PIN keeps an operator from
leaving by accident; it is not a security boundary, because anyone who can edit `station.json` can remove it, and Windows keys cannot be blocked.

### Scanners are read by their terminator
Keyboard-wedge scanners end a code with Enter or Tab, which `ScanSequencer` turns into "stay", "next field", "focus Print" or "print". Timing
heuristics (telling a scan from typing by speed) were left out: they misfire on slow PCs and remote sessions, and the terminator already works for
both people and scanners.
Loading
Loading