From 3105e830388de25911df3e4888d1db5aa669c774 Mon Sep 17 00:00:00 2001 From: josedario87 Date: Wed, 26 Nov 2025 14:47:54 -0600 Subject: [PATCH] =?UTF-8?q?docs:=20Actualizar=20documentaci=C3=B3n=20TM-U2?= =?UTF-8?q?20=20con=20resultados=20de=20pruebas=20reales?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Corregir caracteres por línea: Font A=33 (default), Font B=40 - Documentar que Font A es la fuente por defecto - Agregar charset completo soportado (box drawing, bloques, símbolos) - Documentar comandos que NO funcionan (textPosition, textSmooth, etc) - Corregir sintaxis de operaciones (textAlign, textStyle, feedLine) - Agregar nota: text NO tiene salto de línea automático - Crear resultados-pruebas-tmu220.md con todas las pruebas --- .claude/epson-tmu220-printing-guide.md | 261 ++++++++++++++--------- .claude/resultados-pruebas-tmu220.md | 277 +++++++++++++++++++++++++ server/utils/mcp.ts | 200 +++++++++++++----- 3 files changed, 588 insertions(+), 150 deletions(-) create mode 100644 .claude/resultados-pruebas-tmu220.md diff --git a/.claude/epson-tmu220-printing-guide.md b/.claude/epson-tmu220-printing-guide.md index c744274..d354d7c 100644 --- a/.claude/epson-tmu220-printing-guide.md +++ b/.claude/epson-tmu220-printing-guide.md @@ -1,158 +1,231 @@ -# Guia de Impresion para Epson TM-U220 +# Guía de Impresión para Epson TM-U220 -Esta guia documenta las mejores practicas para generar impresiones legibles en impresoras Epson TM-U220 usando el sistema printerCentral. +Esta guía documenta las mejores prácticas para generar impresiones legibles en impresoras Epson TM-U220 usando el sistema printerCentral. + +> **Nota:** Esta guía fue actualizada el 2025-11-26 basándose en pruebas reales con la impresora "Oficina Mami" (192.168.87.147). ## Especificaciones de la Impresora -| Caracteristica | Valor | +| Característica | Font A | Font B | +|----------------|--------|--------| +| Columnas (normal) | 33 | 40 | +| Columnas (doble ancho) | 16 | 20 | +| Descripción | Normal | Condensada | + +| Característica | Valor | |----------------|-------| -| Columnas (Font A) | 40-42 caracteres | -| Columnas (Font B) | 33-35 caracteres | -| Columnas con doble ancho | ~20 caracteres | -| Caracteres por pulgada | 17.8/16 cpi | | Ancho de papel | 57.5mm, 69.5mm, o 76mm | +| Tipo | Matricial de impacto | -## Reglas Fundamentales - -### 1. Limite de Caracteres por Linea +## Caracteres por Línea (Resumen Rápido) ``` -Texto normal: max 40 caracteres -Texto doble ancho: max 20 caracteres -Texto doble alto: max 40 caracteres -Texto doble ambos: max 20 caracteres +Font A normal (1x1): 33 caracteres +Font A doble ancho (2x1): 16 caracteres +Font B normal (1x1): 40 caracteres +Font B doble ancho (2x1): 20 caracteres ``` -### 2. Caracteres Soportados +**Nota:** El doble alto (1x2) NO afecta la cantidad de caracteres horizontales. -**USAR** - Caracteres ASCII basicos: +## Caracteres Soportados + +### ✅ FUNCIONAN (todos probados) + +**ASCII Básico:** ``` -= - _ * + | / \ ( ) [ ] < > -A-Z a-z 0-9 += - , : . ; " ' [ ] { } ( ) / | \ * # @ $ % & ^ ~ ` _ + < > +A-Z a-z 0-9 espacio ``` -**EVITAR** - Caracteres Unicode extendidos: +**Box Drawing (para tablas):** +``` +Líneas simples: ─ │ ┌ ┐ └ ┘ +Líneas dobles: ═ ║ ╔ ╗ ╚ ╝ +``` + +**Bloques (para gráficos ASCII):** +``` +Sólido: █ +Medios: ▀ ▄ +Sombras: ░ ▒ ▓ +``` + +**Símbolos:** +``` +Círculos: ● ○ ◘ +Flechas: ► ◄ ▲ ▼ +Cartas: ♠ ♣ ♥ ♦ +``` + +**Latino Extendido:** +``` +Español: ñ á é í ó ú ¿ ¡ +Otros: ° ± +``` + +### ❌ NO PROBADOS/EVITAR + ``` -Box drawing: ╔ ═ ╗ ║ ╚ ╝ ┌ ┐ └ ┘ -Simbolos especiales: → ← ↑ ↓ ★ ● ○ Emojis: cualquiera +Caracteres asiáticos +Símbolos muy especiales: → ← ↑ ↓ ★ ``` -### 3. Espaciado con Feed +## Operaciones Soportadas -Siempre usar `feed` para crear espacio visual. La impresora NO interpreta lineas vacias automaticamente. +### Comandos que FUNCIONAN -```json -{ "op": "feed", "lines": 1 } // Espacio simple -{ "op": "feed", "lines": 2 } // Espacio entre secciones -{ "op": "feed", "lines": 4 } // Espacio antes del corte -``` +| Operación | Parámetros | Ejemplo | +|-----------|------------|---------| +| `text` | `value` | `{ "op": "text", "value": "Hola" }` | +| `textAlign` | `align`: left, center, right | `{ "op": "textAlign", "align": "center" }` | +| `textFont` | `font`: font_a, font_b | `{ "op": "textFont", "font": "font_a" }` | +| `textSize` | `width`: 1-2, `height`: 1-2 | `{ "op": "textSize", "width": 2, "height": 1 }` | +| `textStyle` | `em`, `ul` (booleans) | `{ "op": "textStyle", "em": true, "ul": true }` | +| `textDouble` | `dw`, `dh` (booleans) | `{ "op": "textDouble", "dw": true }` | +| `textRotate` | `rotate`: true/false | `{ "op": "textRotate", "rotate": true }` | +| `textLineSpace` | `linespc`: número | `{ "op": "textLineSpace", "linespc": 50 }` | +| `feedLine` | `line`: número | `{ "op": "feedLine", "line": 2 }` | +| `feedUnit` | `unit`: número | `{ "op": "feedUnit", "unit": 50 }` | +| `feed` | (ninguno) | `{ "op": "feed" }` | +| `cut` | (ninguno, sin type) | `{ "op": "cut" }` | + +### Comandos que NO FUNCIONAN + +| Operación | Motivo | +|-----------|--------| +| `textPosition` | No soportado en TM-U220 | +| `textVPosition` | No soportado en TM-U220 | +| `textSmooth` | Sin efecto (es para térmicas) | +| `textLang` | Sin efecto | +| `textStyle.reverse` | No soportado | +| `textStyle.color` | Solo color_1 (negro) funciona | +| `textFont` font_c/d/e | No existen en TM-U220 | +| `textSize` > 2 | Se trata como 2 | +| `cut` con `type` | Genera SchemaError | +| `barcode` | No soportado (matricial) | +| `qrcode` | No soportado (matricial) | +| `imageRaw` | No soportado (matricial) | ## Estructura Recomendada de un Ticket ### Header (Centrado, Destacado) ```json -{ "op": "align", "align": "center" }, -{ "op": "style", "bold": true, "width": 2, "height": 2 }, +{ "op": "textAlign", "align": "center" }, +{ "op": "textSize", "width": 2, "height": 2 }, +{ "op": "textStyle", "em": true }, { "op": "text", "value": "TITULO" }, -{ "op": "style", "bold": false, "width": 1, "height": 1 }, -{ "op": "feed", "lines": 2 } +{ "op": "textStyle", "em": false }, +{ "op": "textSize", "width": 1, "height": 1 }, +{ "op": "feedLine", "line": 2 } ``` +**Importante:** Con doble ancho solo caben 16 caracteres en Font A. + ### Separadores -Siempre con feed antes y despues para que queden en su propia linea: +Usar 33 caracteres `=` para Font A (o 40 para Font B): ```json -{ "op": "text", "value": "================================" }, -{ "op": "feed", "lines": 1 } +{ "op": "text", "value": "=================================" }, +{ "op": "feedLine", "line": 1 } ``` -Para 40 columnas usar 32 caracteres `=` (deja margen visual). - -### Titulos de Seccion - -Usar bold + underline, seguido de feed: +### Títulos de Sección ```json -{ "op": "style", "bold": true, "underline": true }, +{ "op": "textStyle", "em": true, "ul": true }, { "op": "text", "value": "NOMBRE SECCION" }, -{ "op": "style", "bold": false, "underline": false }, -{ "op": "feed", "lines": 1 } +{ "op": "textStyle", "em": false, "ul": false }, +{ "op": "feedLine", "line": 1 } ``` ### Items de Lista -Cada item con su propio feed para legibilidad: - ```json { "op": "text", "value": "[ ] Item uno" }, -{ "op": "feed", "lines": 1 }, +{ "op": "feedLine", "line": 1 }, { "op": "text", "value": "[ ] Item dos" }, -{ "op": "feed", "lines": 1 } +{ "op": "feedLine", "line": 1 } ``` ### Footer y Corte ```json -{ "op": "align", "align": "center" }, +{ "op": "textAlign", "align": "center" }, { "op": "text", "value": "Texto de pie" }, -{ "op": "feed", "lines": 4 }, +{ "op": "feedLine", "line": 4 }, { "op": "cut" } ``` -## Ejemplo Completo: Lista de Compras +## Ejemplo Completo ```json { "operations": [ - { "op": "align", "align": "center" }, - { "op": "style", "bold": true, "width": 2, "height": 2 }, + { "op": "textAlign", "align": "center" }, + { "op": "textSize", "width": 2, "height": 2 }, + { "op": "textStyle", "em": true }, { "op": "text", "value": "MI TITULO" }, - { "op": "style", "bold": false, "width": 1, "height": 1 }, - { "op": "feed", "lines": 2 }, + { "op": "textStyle", "em": false }, + { "op": "textSize", "width": 1, "height": 1 }, + { "op": "feedLine", "line": 2 }, - { "op": "text", "value": "================================" }, - { "op": "feed", "lines": 1 }, - { "op": "style", "bold": true }, + { "op": "text", "value": "=================================" }, + { "op": "feedLine", "line": 1 }, + { "op": "textStyle", "em": true }, { "op": "text", "value": "SUBTITULO" }, - { "op": "feed", "lines": 1 }, - { "op": "style", "bold": false }, - { "op": "text", "value": "================================" }, - { "op": "feed", "lines": 2 }, + { "op": "textStyle", "em": false }, + { "op": "feedLine", "line": 1 }, + { "op": "text", "value": "=================================" }, + { "op": "feedLine", "line": 2 }, - { "op": "align", "align": "left" }, - { "op": "style", "bold": true, "underline": true }, + { "op": "textAlign", "align": "left" }, + { "op": "textStyle", "em": true, "ul": true }, { "op": "text", "value": "SECCION 1" }, - { "op": "style", "bold": false, "underline": false }, - { "op": "feed", "lines": 1 }, + { "op": "textStyle", "em": false, "ul": false }, + { "op": "feedLine", "line": 1 }, { "op": "text", "value": "[ ] Item A" }, - { "op": "feed", "lines": 1 }, + { "op": "feedLine", "line": 1 }, { "op": "text", "value": "[ ] Item B" }, - { "op": "feed", "lines": 2 }, + { "op": "feedLine", "line": 2 }, - { "op": "align", "align": "center" }, - { "op": "text", "value": "================================" }, - { "op": "feed", "lines": 1 }, + { "op": "textAlign", "align": "center" }, + { "op": "text", "value": "=================================" }, + { "op": "feedLine", "line": 1 }, { "op": "text", "value": "Pie de pagina" }, - { "op": "feed", "lines": 4 }, + { "op": "feedLine", "line": 4 }, { "op": "cut" } ] } ``` -## Operaciones Disponibles +## Ejemplo con Box Drawing (Tabla) -| Operacion | Parametros | Ejemplo | -|-----------|------------|---------| -| `text` | `value` | `{ "op": "text", "value": "Hola" }` | -| `feed` | `lines` | `{ "op": "feed", "lines": 2 }` | -| `cut` | - | `{ "op": "cut" }` | -| `align` | `align`: left, center, right | `{ "op": "align", "align": "center" }` | -| `style` | `bold`, `underline`, `width`, `height` | `{ "op": "style", "bold": true }` | +```json +{ + "operations": [ + { "op": "textFont", "font": "font_a" }, + { "op": "text", "value": "╔═══════════════╦═══════════════╗" }, + { "op": "feedLine", "line": 1 }, + { "op": "text", "value": "║ PRODUCTO ║ PRECIO ║" }, + { "op": "feedLine", "line": 1 }, + { "op": "text", "value": "╠═══════════════╬═══════════════╣" }, + { "op": "feedLine", "line": 1 }, + { "op": "text", "value": "║ Cafe ║ $2.50 ║" }, + { "op": "feedLine", "line": 1 }, + { "op": "text", "value": "║ Pan ║ $1.00 ║" }, + { "op": "feedLine", "line": 1 }, + { "op": "text", "value": "╚═══════════════╩═══════════════╝" }, + { "op": "feedLine", "line": 4 }, + { "op": "cut" } + ] +} +``` -## Endpoints de Impresion +## Endpoints de Impresión ### Imprimir Template Guardado @@ -189,18 +262,20 @@ Sintaxis: `{{nombre}}` o `{{nombre:label:default}}` ## Errores Comunes -1. **Texto cortado o ilegible**: Excediste 40 caracteres por linea -2. **Todo pegado**: Falta usar `feed` entre elementos -3. **Caracteres raros**: Usaste Unicode no soportado -4. **Separadores mezclados**: Falta `feed` antes/despues de lineas `===` -5. **Header muy largo**: Con doble ancho solo caben ~20 chars +1. **Texto cortado**: Excediste 33 caracteres (Font A) o 40 (Font B) +2. **Todo pegado**: Falta `feedLine` entre elementos +3. **SchemaError en cut**: Usaste `cut` con parámetro `type` (no soportado) +4. **Header muy largo**: Con doble ancho solo caben 16 chars (Font A) +5. **Colores no funcionan**: Solo funciona color_1 (negro) +6. **Reverse no funciona**: No está soportado en TM-U220 -## Checklist Pre-Impresion +## Checklist Pre-Impresión -- [ ] Ninguna linea excede 40 caracteres (20 si doble ancho) -- [ ] Solo caracteres ASCII basicos -- [ ] `feed` entre cada item para legibilidad -- [ ] `feed` antes y despues de separadores `===` -- [ ] `feed: 4` antes del `cut` final -- [ ] Header centrado con estilo destacado -- [ ] Secciones con titulos bold+underline +- [ ] Ninguna línea excede 33 caracteres (16 si doble ancho) en Font A +- [ ] Ninguna línea excede 40 caracteres (20 si doble ancho) en Font B +- [ ] `feedLine` entre cada elemento para legibilidad +- [ ] `feedLine: 4` antes del `cut` final +- [ ] Header centrado con estilo bold +- [ ] Usando sintaxis correcta: `textAlign`, `textStyle`, `feedLine` +- [ ] `cut` sin parámetro `type` +- [ ] No usando: textPosition, textVPosition, textSmooth, textLang diff --git a/.claude/resultados-pruebas-tmu220.md b/.claude/resultados-pruebas-tmu220.md new file mode 100644 index 0000000..ce50cda --- /dev/null +++ b/.claude/resultados-pruebas-tmu220.md @@ -0,0 +1,277 @@ +# Resultados Pruebas TM-U220 "Oficina Mami" + +**Fecha:** 2025-11-26 +**Impresora:** Oficina Mami (192.168.87.147, matricial2) +**Modelo:** Epson TM-U220 + +--- + +## Prueba 2: Alineaciones + +| Comando | Valor | Resultado | +|---------|-------|-----------| +| `textAlign` | `left` | ✅ Funciona | +| `textAlign` | `center` | ✅ Funciona | +| `textAlign` | `right` | ✅ Funciona | + +**Conclusion:** Todas las alineaciones funcionan correctamente. + +--- + +## Prueba 3: Fuentes + +| Comando | Valor | Resultado | +|---------|-------|-----------| +| `textFont` | `font_a` | ✅ Funciona | +| `textFont` | `font_b` | ✅ Funciona | +| `textFont` | `font_c` | ❌ Sin efecto | +| `textFont` | `font_d` | ❌ Sin efecto | +| `textFont` | `font_e` | ❌ Sin efecto | +| `textFont` | `special_a` | ❌ Sin efecto | +| `textFont` | `special_b` | ❌ Sin efecto | + +**Conclusion:** Solo Font A y Font B funcionan. Las demas fuentes no estan soportadas por el hardware TM-U220. + +--- + +## Prueba 4: Tamanos + +| Comando | Parametros | Resultado | +|---------|------------|-----------| +| `textSize` | `width: 1, height: 1` | ✅ Funciona (normal) | +| `textSize` | `width: 2, height: 1` | ✅ Funciona (doble ancho) | +| `textSize` | `width: 1, height: 2` | ✅ Funciona (doble alto) | +| `textSize` | `width: 2, height: 2` | ✅ Funciona (doble ambos) | +| `textSize` | `width: 3, height: 3` | ⚠️ Redundante (igual a 2x2) | +| `textSize` | `width: 4, height: 4` | ⚠️ Redundante (igual a 2x2) | + +**Conclusion:** TM-U220 solo soporta multiplicadores 1 y 2. Valores mayores son tratados como 2. + +--- + +## Prueba 1: Texto Basico + +| Comando | Resultado | +|---------|-----------| +| `text` | ✅ Funciona | +| `feedLine` | ✅ Funciona | +| Caracteres ASCII (A-Z, a-z, 0-9) | ✅ Funciona | +| Simbolos (= - _ * + \| / \\ ( ) [ ]) | ✅ Funciona | + +**Conclusion:** Texto basico funciona al 100%. + +--- + +## Prueba 5: Estilos + +| Comando | Parametros | Resultado | +|---------|------------|-----------| +| `textStyle` | (sin estilo) | ✅ Funciona (normal) | +| `textStyle` | `em: true` (bold) | ✅ Funciona | +| `textStyle` | `ul: true` (underline) | ✅ Funciona | +| `textStyle` | `em: true, ul: true` | ✅ Funciona (bold+underline) | +| `textStyle` | `reverse: true` | ❌ No funciona | +| `textStyle` | `color: color_1` (negro) | ✅ Funciona | +| `textStyle` | `color: color_2` (rojo) | ❌ No funciona | +| `textStyle` | `color: color_3` | ❌ No funciona | +| `textStyle` | `color: color_4` | ❌ No funciona | + +**Conclusion:** Solo funcionan bold, underline y color negro. Reverse y colores 2-4 no estan soportados. + +--- + +## Prueba 6: Doble Ancho/Alto (textDouble) + +| Comando | Parametros | Resultado | +|---------|------------|-----------| +| `textDouble` | `dw: false, dh: false` | ✅ Funciona (normal) | +| `textDouble` | `dw: true, dh: false` | ✅ Funciona (doble ancho) | +| `textDouble` | `dw: false, dh: true` | ✅ Funciona (doble alto) | +| `textDouble` | `dw: true, dh: true` | ✅ Funciona (doble ambos) | + +**Conclusion:** textDouble funciona igual que textSize. Ambos comandos son equivalentes para TM-U220. + +--- + +## Prueba 7: Espaciado de Lineas + +| Comando | Parametros | Resultado | +|---------|------------|-----------| +| `textLineSpace` | (default) | ✅ Funciona | +| `textLineSpace` | `linespc: 30` | ✅ Funciona | +| `textLineSpace` | `linespc: 60` | ✅ Funciona | +| `textLineSpace` | `linespc: 100` | ✅ Funciona | + +**Conclusion:** Espaciado de lineas funciona correctamente. Valores mayores = mas espacio entre lineas. + +--- + +## Prueba 8: Rotacion + +| Comando | Parametros | Resultado | +|---------|------------|-----------| +| `textRotate` | `rotate: false` | ✅ Funciona (0 grados, normal) | +| `textRotate` | `rotate: true` | ✅ Funciona (90 grados clockwise) | +| `textRotate` | `rotate_0, rotate_90, rotate_180, rotate_270` | ❌ Sin efecto (no soportado) | + +**Conclusion:** Solo 0 y 90 grados soportados. Angulos arbitrarios no son posibles en impresoras matriciales. + +--- + +## Prueba 9: Posicionamiento Horizontal + +| Comando | Parametros | Resultado | +|---------|------------|-----------| +| `textPosition` | `x: 0` | ❌ No funciona | +| `textPosition` | `x: 50` | ❌ No funciona | +| `textPosition` | `x: 100` | ❌ No funciona | +| `textPosition` | `x: 150` | ❌ No funciona | +| `textPosition` | `x: 200` | ❌ No funciona | + +**Conclusion:** textPosition NO funciona en TM-U220. El posicionamiento horizontal absoluto no esta soportado. + +--- + +## Prueba 10: Feed tipos + +| Comando | Parametros | Resultado | +|---------|------------|-----------| +| `feed` | (simple) | ✅ Funciona | +| `feedLine` | `line: 1` | ✅ Funciona | +| `feedLine` | `line: 3` | ✅ Funciona | +| `feedUnit` | `unit: 20` | ✅ Funciona | +| `feedUnit` | `unit: 50` | ✅ Funciona | +| `feedUnit` | `unit: 100` | ✅ Funciona | + +**Conclusion:** Todos los tipos de feed funcionan correctamente. feedUnit permite control mas preciso que feedLine. + +--- + +## Prueba 14: Corte + +| Comando | Parametros | Resultado | +|---------|------------|-----------| +| `cut` | (sin tipo) | ✅ Funciona | +| `cut` | `type: no_feed` | ❌ SchemaError | +| `cut` | `type: feed` | ❌ SchemaError | +| `cut` | `type: reserve` | ❌ SchemaError | +| `cut` | `type: feed_fullcut` | ❌ SchemaError | +| `cut` | multiples cuts seguidos | ❌ SchemaError | + +**Conclusion:** Solo el corte simple (sin parametro type) funciona. Los tipos especificos de corte generan error. + +--- + +## Prueba: textSmooth (Suavizado) + +| Comando | Parametros | Resultado | +|---------|------------|-----------| +| `textSmooth` | `smooth: false` | ❌ Sin efecto visible | +| `textSmooth` | `smooth: true` | ❌ Sin efecto visible | +| `textSmooth` | con texto 2x2 | ❌ Sin efecto visible | + +**Conclusion:** textSmooth no tiene efecto en TM-U220. El suavizado es para impresoras termicas con capacidad grafica. + +--- + +## Prueba: textLang (Idioma/Charset) + +| Comando | Parametros | Resultado | +|---------|------------|-----------| +| `textLang` | `lang: en` | ❌ Sin efecto | +| `textLang` | `lang: es` | ❌ Sin efecto | +| `textLang` | `lang: ja` | ❌ Sin efecto | +| `textLang` | `lang: de` | ❌ Sin efecto | + +**Conclusion:** textLang no cambia el charset. Solo se imprimen caracteres del alfabeto ingles basico (ASCII). + +--- + +## Prueba: textVPosition (Posicion Vertical) + +| Comando | Parametros | Resultado | +|---------|------------|-----------| +| `textVPosition` | `y: 0` | ❌ No funciona | +| `textVPosition` | `y: 50` | ❌ No funciona | +| `textVPosition` | `y: 100` | ❌ No funciona | +| `textVPosition` | `y: 200` | ❌ No funciona | + +**Conclusion:** textVPosition NO funciona en TM-U220, igual que textPosition. Posicionamiento absoluto no soportado. + +--- + +## Resumen de Compatibilidad TM-U220 + +| Categoria | Comandos Funcionales | Comandos No Soportados | +|-----------|---------------------|------------------------| +| Texto | text | - | +| Alineacion | left, center, right | - | +| Fuentes | font_a, font_b | font_c, font_d, font_e, special_a, special_b | +| Tamanos | 1x1, 2x1, 1x2, 2x2 | >2 (redundante) | +| Estilos | bold (em), underline (ul), color_1 | reverse, color_2, color_3, color_4 | +| textDouble | dw, dh | - (equivalente a textSize) | +| Espaciado | textLineSpace (cualquier valor) | - | +| Rotacion | rotate: false (0°), rotate: true (90°) | Angulos arbitrarios | +| Posicion | - | textPosition, textVPosition (no funcionan) | +| Feed | feed, feedLine, feedUnit | - | +| Corte | cut (simple, sin tipo) | cut con type (SchemaError) | +| Suavizado | - | textSmooth (sin efecto) | +| Idioma | - | textLang (sin efecto, solo ASCII) | + +--- + +## Caracteres por Linea + +| Fuente | Tamano | Caracteres/Linea | +|--------|--------|------------------| +| Font A | 1x1 | 33 | +| Font A | 2x1 (doble ancho) | 16 | +| Font A | 1x2 (doble alto) | 33 | +| Font A | 2x2 (doble ambos) | 16 | +| Font B | 1x1 | 40 | +| Font B | 2x1 (doble ancho) | 20 | +| Font B | 1x2 (doble alto) | 40 | +| Font B | 2x2 (doble ambos) | 20 | + +**Observaciones:** +- Font B es mas condensada y permite mas caracteres por linea +- El doble alto (1x2) no afecta la cantidad de caracteres horizontales +- El doble ancho (2x1 y 2x2) reduce los caracteres a la mitad + +--- + +## Caracteres Soportados + +### ASCII Basico (todos funcionan, 33 chars/linea en Font A 1x1) +``` += - , : . ; " [ { ( / | * # @ $ % & ^ ~ ` \ _ + < > ' +A-Z a-z 0-9 espacio +``` + +### Box Drawing (todos funcionan) +``` +Lineas simples: ─ │ ┌ ┐ └ ┘ +Lineas dobles: ═ ║ ╔ ╗ ╚ ╝ +``` + +### Bloques (todos funcionan) +``` +Solido: █ +Medios: ▀ ▄ +Sombras: ░ ▒ ▓ +``` + +### Simbolos (todos funcionan) +``` +Circulos: ● ○ ◘ +Flechas: ► ◄ ▲ ▼ +Cartas: ♠ ♣ ♥ ♦ +``` + +### Latinos Extendidos (todos funcionan) +``` +Espanol: ñ á é í ó ú ¿ ¡ +Otros: ° ± +``` + +**Conclusion:** La TM-U220 soporta un charset muy amplio incluyendo box drawing, bloques y simbolos especiales. Todos ocupan el mismo ancho (monospace). diff --git a/server/utils/mcp.ts b/server/utils/mcp.ts index 5af7e70..9ea326e 100644 --- a/server/utils/mcp.ts +++ b/server/utils/mcp.ts @@ -13,12 +13,17 @@ export const PRINTING_GUIDES: Record rules: string[] + operationsSupported?: Record + operationsNotSupported?: string[] tips?: string[] operations: string[] example: string @@ -26,66 +31,127 @@ export const PRINTING_GUIDES: Record " \' ` @ # % & ^ ~', + 'ASCII completo: A-Z a-z 0-9 = - _ * + | / \\ ( ) [ ] < > " \' ` @ # $ % & ^ ~ , : . ; !', 'Box Drawing Doble: ╔ ╗ ╚ ╝ ║ ═', 'Box Drawing Simple: ┌ ┐ └ ┘ │ ─ ├ ┤ ┬ ┴ ┼', 'Bloques y Sombras: █ ▓ ▒ ░ ▀ ▄', - 'Latinos extendidos: ñ Ñ á é í ó ú Á É Í Ó Ú ¿ ¡ ç', - 'Monedas: $ € £ ¥', - 'Matemáticos: ± × ÷ ≤ ≥ ∞' + 'Flechas: ► ◄ ▲ ▼', + 'Circulos: ● ○ ◘', + 'Cartas: ♠ ♣ ♥ ♦', + 'Latinos: ñ Ñ á é í ó ú ¿ ¡', + 'Otros: ° ±' ], notSupported: [ - 'Flechas Unicode: → ← ↑ ↓ ↔ ⇒ ⇐', - 'Estrellas/Círculos: ★ ☆ ● ○ ◆ ◇', - 'Emojis (todos): 😀 ❤ ✓ ✗ ☀ ☁ ✔ ✘', - 'Específicos: ₿ (Bitcoin) ≠ (Distinto)' + 'Emojis (todos)', + 'Flechas thin Unicode: → ← ↑ ↓' ] }, + fonts: { + font_a: { columns: 33, columnsDoubleWidth: 16, description: 'Fuente normal (DEFAULT - se usa automaticamente)' }, + font_b: { columns: 40, columnsDoubleWidth: 20, description: 'Fuente condensada (hay que activarla con textFont)' } + }, rules: [ - 'Máximo 40 caracteres por línea (20 con width:2)', - 'Siempre usar feed entre elementos para legibilidad', - 'feed:1 entre items, feed:2 entre secciones', - 'feed:4 antes del cut final', - 'Los headers con width:2 deben ser max 20 chars', + '╔══════════════════════════════════════════════════════════════╗', + '║ CARACTERES POR LINEA - LA FUENTE POR DEFECTO ES FONT A ║', + '╠══════════════════════════════════════════════════════════════╣', + '║ FONT A (DEFAULT): ║', + '║ - Normal (width:1): 33 caracteres por linea ║', + '║ - Doble ancho (width:2): 16 caracteres por linea ║', + '║ FONT B (condensada, hay que activarla con textFont): ║', + '║ - Normal (width:1): 40 caracteres por linea ║', + '║ - Doble ancho (width:2): 20 caracteres por linea ║', + '║ IMPORTANTE: height NO afecta la cantidad de caracteres ║', + '╚══════════════════════════════════════════════════════════════╝', + 'Por defecto la impresora usa Font A, entonces el maximo es 33 chars', + 'Para usar Font B: { "op": "textFont", "font": "font_b" }', + '=== REGLAS DE FORMATO ===', + 'text NO tiene salto de linea automatico, usar feedLine despues de cada text', + 'Siempre usar feedLine entre elementos para legibilidad', + 'feedLine:1 entre items, feedLine:2 entre secciones', + 'feedLine:4 antes del cut final', + 'Solo usar cut SIN parametro type (cut con type da SchemaError)', 'Docs largos pueden dar EX_TIMEOUT pero se imprimen igual' ], + operationsSupported: { + text: { op: 'text', params: 'value: string', description: 'Imprime texto' }, + textAlign: { op: 'textAlign', params: 'align: left|center|right', description: 'Alineacion' }, + textFont: { op: 'textFont', params: 'font: font_a|font_b', description: 'Fuente (solo A y B funcionan)' }, + textSize: { op: 'textSize', params: 'width: 1-2, height: 1-2', description: 'Tamano (max 2, valores >2 son igual a 2)' }, + textStyle: { op: 'textStyle', params: 'em: bool, ul: bool', description: 'Solo bold y underline funcionan' }, + textDouble: { op: 'textDouble', params: 'dw: bool, dh: bool', description: 'Alternativa a textSize' }, + textRotate: { op: 'textRotate', params: 'rotate: bool', description: 'Solo 0 y 90 grados' }, + textLineSpace: { op: 'textLineSpace', params: 'linespc: number', description: 'Espaciado entre lineas' }, + feed: { op: 'feed', params: 'ninguno', description: 'Avance simple' }, + feedLine: { op: 'feedLine', params: 'line: number', description: 'Avance N lineas' }, + feedUnit: { op: 'feedUnit', params: 'unit: number', description: 'Avance en dots (mas preciso)' }, + cut: { op: 'cut', params: 'ninguno', description: 'Corte (NO usar type, da error)' }, + pulse: { op: 'pulse', params: 'drawer: drawer_1|drawer_2, time: pulse_100-500', description: 'Abrir cajon' } + }, + operationsNotSupported: [ + 'textPosition (posicion X no funciona)', + 'textVPosition (posicion Y no funciona)', + 'textSmooth (sin efecto)', + 'textLang (sin efecto, solo ASCII)', + 'textStyle.reverse (no funciona)', + 'textStyle.color (solo color_1/negro)', + 'textFont font_c/d/e/special (sin efecto)', + 'cut con type (SchemaError)', + 'barcode (matricial no soporta)', + 'qrcode (matricial no soporta)', + 'imageRaw (matricial no soporta)' + ], tips: [ - 'TABLAS: Usar box drawing ┌─┬─┐ │ ├─┼─┤ └─┴─┘ para tablas legibles', + 'TABLAS: Usar box drawing ┌─┬─┐ │ ├─┼─┤ └─┴─┘', 'BARRAS PROGRESO: Combinar █ y ░ ej: [█████░░░░░]', - 'CAJAS: Box doble ╔═╗ ║ ╚═╝ para destacar contenido importante', - 'BULLETS: Usar * - + > o [*] [X] en lugar de ✓ ✗', - 'ASCII ART: Funciona perfecto con caracteres básicos' + 'CAJAS: Box doble ╔═╗ ║ ╚═╝ para destacar', + 'BULLETS: Usar ● ○ ► o [X] [ ]', + 'ASCII ART: Funciona perfecto con todos los caracteres' ], operations: [ '{ op: "text", value: "texto" } - Imprime texto', - '{ op: "feed", lines: N } - Avanza N líneas', - '{ op: "cut" } - Corta el papel', - '{ op: "align", align: "left|center|right" } - Alineación', - '{ op: "style", bold: true, underline: true, width: 1-2, height: 1-2 } - Estilos' + '{ op: "feedLine", line: N } - Avanza N lineas', + '{ op: "cut" } - Corta el papel (SIN type)', + '{ op: "textAlign", align: "left|center|right" } - Alineacion', + '{ op: "textFont", font: "font_a|font_b" } - Fuente', + '{ op: "textSize", width: 1-2, height: 1-2 } - Tamano', + '{ op: "textStyle", em: true, ul: true } - Bold y underline', + '{ op: "textRotate", rotate: true } - Rotar 90 grados', + '{ op: "pulse", drawer: "drawer_1", time: "pulse_100" } - Abrir cajon' ], example: `[ - { "op": "align", "align": "center" }, - { "op": "style", "bold": true, "width": 2, "height": 2 }, + { "op": "textAlign", "align": "center" }, + { "op": "textSize", "width": 2, "height": 2 }, + { "op": "textStyle", "em": true }, { "op": "text", "value": "TITULO" }, - { "op": "style", "bold": false, "width": 1, "height": 1 }, - { "op": "feed", "lines": 2 }, - { "op": "text", "value": "╔══════════════════════════════════════╗" }, - { "op": "text", "value": "║ Contenido importante aquí ║" }, - { "op": "text", "value": "╚══════════════════════════════════════╝" }, - { "op": "feed", "lines": 1 }, - { "op": "text", "value": "┌────────┬────────┬────────┐" }, - { "op": "text", "value": "│ COL 1 │ COL 2 │ COL 3 │" }, - { "op": "text", "value": "├────────┼────────┼────────┤" }, - { "op": "text", "value": "│ dato │ dato │ dato │" }, - { "op": "text", "value": "└────────┴────────┴────────┘" }, - { "op": "feed", "lines": 1 }, - { "op": "text", "value": "Progreso: [██████████░░░░░░░░░░] 50%" }, - { "op": "feed", "lines": 4 }, + { "op": "textStyle", "em": false }, + { "op": "textSize", "width": 1, "height": 1 }, + { "op": "feedLine", "line": 2 }, + { "op": "text", "value": "╔═══════════════════════════════╗" }, + { "op": "feedLine", "line": 1 }, + { "op": "text", "value": "║ Contenido importante ║" }, + { "op": "feedLine", "line": 1 }, + { "op": "text", "value": "╚═══════════════════════════════╝" }, + { "op": "feedLine", "line": 1 }, + { "op": "textAlign", "align": "left" }, + { "op": "text", "value": "┌──────────┬──────────┬─────────┐" }, + { "op": "feedLine", "line": 1 }, + { "op": "text", "value": "│ COL 1 │ COL 2 │ COL 3 │" }, + { "op": "feedLine", "line": 1 }, + { "op": "text", "value": "├──────────┼──────────┼─────────┤" }, + { "op": "feedLine", "line": 1 }, + { "op": "text", "value": "│ dato │ dato │ dato │" }, + { "op": "feedLine", "line": 1 }, + { "op": "text", "value": "└──────────┴──────────┴─────────┘" }, + { "op": "feedLine", "line": 1 }, + { "op": "text", "value": "Progreso: [████████░░░░░] 60%" }, + { "op": "feedLine", "line": 4 }, { "op": "cut" } ]` }, @@ -227,29 +293,49 @@ export const MCP_TOOLS = [ name: 'printercentral_print_raw', description: `Imprime operaciones ePOS directamente. Útil para impresiones personalizadas sin crear un template. -FORMATO DE OPERACIONES (para impresora TM-U220, max 40 caracteres por línea): -- { op: "text", value: "texto" } - Imprime texto -- { op: "feed", lines: N } - Avanza N líneas (usar entre elementos para legibilidad) -- { op: "cut" } - Corta el papel -- { op: "align", align: "left|center|right" } - Alinea el texto -- { op: "style", bold: true/false, underline: true/false, width: 1-2, height: 1-2 } - Estilo de texto +╔═══════════════════════════════════════════════════════╗ +║ CARACTERES POR LÍNEA - FONT A ES EL DEFAULT ║ +╠═══════════════════════════════════════════════════════╣ +║ FONT A (DEFAULT - no necesita textFont): ║ +║ Normal (width:1): 33 caracteres ║ +║ Doble ancho (width:2): 16 caracteres ║ +║ FONT B (activar con textFont font_b): ║ +║ Normal (width:1): 40 caracteres ║ +║ Doble ancho (width:2): 20 caracteres ║ +║ NOTA: height NO afecta cantidad de caracteres ║ +╚═══════════════════════════════════════════════════════╝ +DEFAULT = Font A = 33 chars max (o 16 con width:2) + +OPERACIONES DISPONIBLES: +- { op: "text", value: "texto" } - Imprime texto (SIN salto de linea automatico) +- { op: "feedLine", line: N } - Avanza N líneas (SIEMPRE usar despues de text) +- { op: "cut" } - Corta papel (SIN parametro type) +- { op: "textAlign", align: "left|center|right" } - Alineación +- { op: "textFont", font: "font_a|font_b" } - Selecciona fuente +- { op: "textSize", width: 1-2, height: 1-2 } - Tamaño +- { op: "textStyle", em: true, ul: true } - Bold y underline +- { op: "textRotate", rotate: true } - Rotar 90° +- { op: "pulse", drawer: "drawer_1", time: "pulse_100" } - Abrir cajón + +CHARSET SOPORTADO: +ASCII, Box Drawing (┌─┐│└┘╔═╗║╚╝), Bloques (█▓▒░▀▄), Símbolos (●○◘►◄▲▼♠♣♥♦), Latinos (ñáéíóú¿¡°±) + +NO FUNCIONA en TM-U220: +textPosition, textVPosition, textSmooth, textLang, textStyle.reverse, textStyle.color (solo negro), cut con type, barcode, qrcode, imageRaw EJEMPLO: [ - { "op": "align", "align": "center" }, - { "op": "style", "bold": true, "width": 2, "height": 2 }, + { "op": "textAlign", "align": "center" }, + { "op": "textSize", "width": 2, "height": 2 }, + { "op": "textStyle", "em": true }, { "op": "text", "value": "TITULO" }, - { "op": "style", "bold": false, "width": 1, "height": 1 }, - { "op": "feed", "lines": 2 }, + { "op": "textStyle", "em": false }, + { "op": "textSize", "width": 1, "height": 1 }, + { "op": "feedLine", "line": 2 }, { "op": "text", "value": "Contenido aquí" }, - { "op": "feed", "lines": 4 }, + { "op": "feedLine", "line": 4 }, { "op": "cut" } -] - -REGLAS IMPORTANTES: -- Max 40 caracteres por línea (20 con width:2) -- Usar solo caracteres ASCII (evitar unicode especial) -- Siempre terminar con feed y cut`, +]`, inputSchema: { type: 'object' as const, properties: {