Skip to main content

brother-ql-labels

Print labels on a networked Brother QL printer.

설치로 이동

소스 정보

저장소
kimasplund/kyyhky
최근 소스 활동
2026년 8월 29일 16:53
감지된 SKILL.md 언어
영어
스타
0
포크
0

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
brother-ql-labels
description
Print labels on a networked Brother QL printer.
version
1.1.0
license
MIT
platforms
["linux","macos","windows"]
metadata
{"hermes":{"tags":["Printing","Labels","Brother","QL-580N","Addresses","Barcode","QR","CSV"]}}
# Brother QL labels (Kyyhky) ## When to Use Use whenever the user wants something **printed on a physical label** — addresses for post, shipping, parcels, filing, storage, asset tags, product labels, name badges, or anything with a **bar code or QR code** on it. Triggers include: "print a label", "print these addresses", "label this parcel", "make asset tags", "print barcode labels", "QR labels for these links", or handing over a CSV/spreadsheet. Also use it to diagnose a QL-580N: blank labels, mirrored text, jobs that vanish silently, or cutter behaviour. **Not** for PDF/paper documents, and not for designing artwork. ## Two modes 1. **Addresses** — `kyyhky print --csv addr.csv`. Auto-sized type, no layout work needed. 2. **Anything else** — a JSON/YAML **template** listing elements (text, bar code, QR, image, line, box) at millimetre positions, filled from a CSV. Start with `kyyhky templates` to see the built-ins. Reach for a template as soon as the label is not purely an address. ## Setup ```bash pip install "kyyhky[all] @ git+https://github.com/kimasplund/kyyhky" export KYYHKY_HOST=192.168.1.50 # or pass --host on every command ``` The `[all]` extra pulls in `segno` (QR), `python-barcode` and `PyYAML`. Plain `pip install git+...` is enough for addresses only. Find the printer if the address is unknown: `kyyhky discover`. There is no Brother SDK for Linux for this model. Kyyhky speaks the raster protocol directly on port 9100, per Brother's *QL-500/550/560/570/580N/650TD/700/1050/1060N Raster Command Reference*. ## Quick reference ```bash kyyhky discover # scan the LAN for printers kyyhky status # is the printer reachable? kyyhky media # supported label sizes kyyhky fonts # usable font families kyyhky templates # built-in custom layouts kyyhky symbologies # bar code types + QR options kyyhky sample --out addr.csv # example CSV to fill in # ALWAYS preview before printing -- it costs nothing kyyhky preview --csv addr.csv --out labels.png --scale 2 kyyhky print --csv addr.csv --yes kyyhky print --csv addr.csv --cut-every 10 --yes kyyhky print --csv addr.csv --no-cut --yes # leave on the roll # one-off label, no file needed kyyhky print --to 'Ada Lovelace' \ --street 'Wilton Place' --number 12 --apartment 5 \ --postal 'SW1X 8RL' --city London --country 'United Kingdom' --yes ``` Omit `--yes` for an interactive confirmation. `--dry-run` builds the job and reports its size without sending anything. Running from a clone instead of an install: `python3 -m kyyhky.cli ...`. ## Custom layouts (bar codes, QR, anything non-address) ```bash kyyhky templates # what is built in kyyhky template-init asset --out my.json # copy one out to edit kyyhky template-preview my.json --data items.csv --out check.png kyyhky template-print my.json --data items.csv --yes ``` Built-ins: `address`, `shipping`, `asset`, `product`, `qr-only`, `name-badge`. Preview any of them with no data at all — `kyyhky template-preview asset --out a.png` renders a sample row. A template is a media size plus a list of elements. **Positions are millimetres from the top-left**, as you would measure with a ruler: ```json { "label": "29x90", "elements": [ {"type": "text", "text": "{name}", "x": 4, "y": 2, "size": 4.5, "bold": true, "max_width": 52}, {"type": "text", "text": "{id}", "x": 4, "y": 8, "size": 3.2}, {"type": "barcode", "data": "{id}", "x": 4, "y": 12.5, "width": 52, "height": 8, "symbology": "code128"}, {"type": "qr", "data": "{url}", "x": -4, "y": 2, "size": 24} ] } ``` | Type | Key options | |------|-------------| | `text` | `text`, `size` (mm), `bold`, `max_width`, `align`, `font` | | `barcode` | `data`, `symbology`, `width` or `module`, `height`, `text_below` | | `qr` | `data`, `size` or `module`, `ecc` (l/m/q/h), `micro` | | `image` | `path`, `width`, `height`, `threshold`, `invert` | | `line` | `x`, `y`, `x2`/`y2` or `length` + `vertical`, `thickness` | | `box` | `x`, `y`, `width`, `height`, `thickness`, `filled` | Rules worth knowing: * `{column}` placeholders match **case-, space- and underscore-insensitively**, so `{Product Name}` and `{product_name}` read the same CSV column. A missing column renders empty rather than failing. * **Negative `x`/`y` anchor to the right/bottom edge** — `"x": -4` sits 4 mm in from the right. * Omit `x` and set `align` to `center`/`right`; omit `y` and set `valign` to `middle`/`bottom`. * Any length can be given in dots with an `_dots` suffix (`"x_dots": 120`). * `max_width` shrinks text to fit instead of running off the label. * A `copies` column prints that row more than once. * Without `--data`, use `--set key=value` (repeatable) for a one-off label. Rendering **warns** when elements run off the label or **collide with each other**. Read those warnings — they are the difference between a good label and a wasted one. ## Bar codes and QR `code128` is the right default for anything alphanumeric. `kyyhky symbologies` lists all 13 with what each accepts. Both are rendered from the raw module matrix at an **exact integer number of printer dots per module**, never by scaling a bitmap. This is what makes small codes scan reliably; quiet zones are included automatically. Verified on hardware — printed labels scan with a phone. Gotchas: * `code39` appends a `$` checksum in most libraries. Kyyhky turns that **off** by default; pass `"checksum": true` if you need it. * `ean13`/`upca` require an exact digit count and add their own check digit. A wrong length is an error naming the offending element. * QR `size` is the box it must fit inside; the module size is computed from it. A tight `size` on a busy payload gives a code too dense to scan — prefer fewer characters (a short URL) over a smaller module. ## Label layout Bold recipient name, then one line each, blanks skipped automatically: ``` Ada Lovelace <- bold, largest att: Purchasing <- only if an att/c-o column exists Wilton Place 12 as 5 <- street + number + apartment SW1X 8RL London <- postal + city UNITED KINGDOM <- country, upper-cased ``` Font size is chosen automatically: the renderer starts at `--max-size` and steps down until everything fits inside the 306 x 991 dot print area. A typical address lands at 66/50 pt; long ones shrink gracefully. If a label bottoms out at `--min-size` the CLI flags it as `<-- TIGHT` in the listing. ## CSV format Headers are matched case-insensitively in English, Finnish and Swedish, so most spreadsheet exports work unchanged. Delimiter (`,` `;` tab `|`) is sniffed, and a UTF-8 BOM is handled -- European Excel exports just work. ```csv name,att,street,number,apartment,postal,city,country,copies Ada Lovelace,,Wilton Place,12,5,SW1X 8RL,London,United Kingdom,1 Example Oy,Purchasing,Mannerheimintie,140,A 3,00250,Helsinki,Finland,2 ``` | Field | Also accepted | |-------|---------------| | `name` | recipient, to, company, nimi, vastaanottaja, namn | | `att` | attn, attention, c/o, care_of, dept, osasto | | `street` | address, address1, katuosoite, katu, gata, adress | | `number` | no, nr, house_number, nro, numero | | `apartment` | apt, flat, unit, suite, address2, as, asunto, lgh | | `postal` | zip, postcode, post_no, postinumero, postnummer | | `city` | town, postitoimipaikka, kaupunki, ort, postort | | `country` | maa, land | | `copies` | qty, quantity, kpl, antal | `.json` and `.jsonl` work too. `copies` prints that record N times. Bare numeric apartments gain a qualifier (`5` -> `as 5`); anything already qualified (`A 3`, `apt 9`) is left alone. An `att` value that already starts with `att`/`attn`/`c/o` is not double-prefixed. ## Hardware facts (verified on real hardware) These four cost real labels to establish. Do not re-derive them. 1. **TIFF/PackBits compression is mandatory over LAN.** Section 5: *"In case QL-580N/1060N, serial and LAN interface should set TIFF option."* An uncompressed job over 9100 will not print. Never pass `--no-compress`. 2. **Byte 0 of a raster line is the RIGHT margin.** Section 3.2.5. Offsetting by the left margin instead prints a **blank label** -- content lands on pins that overhang the media. (The popular `brother_ql` library assumes the opposite; for this model that is wrong.) 3. **The pin axis runs right-to-left, so the image must be pre-flipped.** Without it the text prints **mirrored**. Critically, flip the *image* before pasting it at the margin offset -- flipping the assembled 720-pin canvas moves content from pins 6..311 to 408..713 and prints blank. 4. **No status over Ethernet.** `ESC i S` never answers on the LAN board; section 6.9 defines no status channel for network printing. `status` reporting "not reported" is normal, not a fault. Printing still works. Media/error detection is USB/serial only. ## Cutting **Default: one cut at the end of the job.** A run of address labels comes off as a single strip, which is easier to carry and stick than loose labels. | Flag | Effect | |------|--------| | *(default)* | `--cut end` — one cut after the whole run | | `--cut each` | cut after every label | | `--cut-every 10` | cut after every 10 labels (implies `--cut every`) | | `--no-cut` | cutter fully off, labels stay on the roll | | `--no-cut-at-end` | suppress the final cut, whatever `--cut` says | Two independent bits drive the cutter and both matter: | Mode | `ESC i M` | `ESC i K` | `ESC i A` | |------|-----------|-----------|-----------| | `end` (default) | `0x00` | `0x08` | — | | `each` | `0x40` | `0x08` | 1 | | `--cut-every 10` | `0x40` | `0x08` | 10 | | `never` | `0x00` | `0x00` | — | `ESC i M` bit 6 cuts *between* labels; `ESC i K` bit 3 cuts after the *final* label. Clearing only the first still chops the roll once at the end — that is why `--no-cut` must clear both. `ESC i A` is only emitted when auto-cut is on. `python3 tools/show_cut_modes.py` prints this table from live job bytes. The `print` command reports the mode in its header (`Cut : ...`) before sending, so the behaviour is never a surprise. ## Geometry (29 x 90 mm) | Property | Value | |----------|-------| | Print area | 306 x 991 dots (25.91 x 83.90 mm) | | Left / right margin pins | 408 / 6 | | Raster line | 90 bytes (720 pins) | | Resolution | 300 dpi (`--hires` gives 600 dpi lengthwise) | `kyyhky media` lists all 18 supported sizes. Continuous tape also needs `--length MM`. ## Useful options | Flag | Purpose | |------|---------| | `--limit N` | only the first N **rows** (a row with `copies=2` still yields 2 labels) | | `--font` | `dejavu` (default, full Nordic coverage), `inter`, `liberation`, `condensed`, or a path | | `--align center` / `--valign top\|middle\|bottom` | text placement | | `--pad MM` | inner margin, default 1.6 | | `--border` | hairline around the printable area (calibration aid) | | `--rotate cw\|ccw` | reading direction; cosmetic on 29x90, both read fine | | `--save-job FILE` | dump the raw job bytes for inspection | ## Verifying without wasting labels `tools/decode_job.py` parses a built job back into a PNG, reports which pins the ink occupies, and warns if anything falls outside the printable window: ```bash python3 tools/decode_job.py # writes /tmp/decoded_as_printed.png ``` `as_printed` models the pin-axis reversal, so it shows what the label will physically look like. Use this before any risky change to the raster path. `kyyhky calibrate` prints two probe labels (`cw` and `ccw`) with borders, for when media or firmware changes. ## Troubleshooting | Symptom | Cause | |---------|-------| | `no printer address` | pass `--host <ip>` or export `KYYHKY_HOST` | | Blank labels | content outside the print window -- check the margin offset and that mirroring is applied to the image, not the canvas | | Mirrored text | pin axis not reversed (`--no-mirror` was passed) | | Nothing prints, no error | compression disabled -- LAN needs TIFF | | `status` shows nothing | expected; the Ethernet board has no status channel | | `discover` finds nothing | cold ARP cache; it already sweeps twice, try `--timeout 1.0` |
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기