// Emulador de impresora térmica ESC/POS con conexión LAN (TCP 9100) y USB // (a través de USB/IP). package main import ( "flag" "fmt" "os" "os/signal" "escpos-emulator/internal/escpos" "escpos-emulator/internal/gui" "escpos-emulator/internal/lan" "escpos-emulator/internal/usbip" ) func main() { lanAddr := flag.String("lan", ":9100", "dirección TCP del puerto RAW; vacío para desactivar") usbAddr := flag.String("usbip", ":3240", "dirección del servidor USB/IP; vacío para desactivar") profileKey := flag.String("perfil", "80mm", "modelo emulado: 80mm o 58mm") noGUI := flag.Bool("nogui", false, "sin ventana: registro por consola y tickets a PNG") ticketDir := flag.String("tickets", "", "carpeta donde guardar cada ticket cortado como PNG (en -nogui: \"tickets\")") flag.Parse() prof, ok := escpos.FindProfile(*profileKey) if !ok { fmt.Fprintf(os.Stderr, "perfil desconocido %q. Disponibles:\n", *profileKey) for _, p := range escpos.Profiles() { fmt.Fprintf(os.Stderr, " %-6s %s\n", p.Key, p.Name) } os.Exit(2) } p, err := escpos.NewPrinter(prof) if err != nil { fatal("no se pudo crear la impresora: %v", err) } if *noGUI { p.SetLogOutput(os.Stdout) if *ticketDir == "" { *ticketDir = "tickets" } } if dir := *ticketDir; dir != "" { p.SetOnTicket(func(t *escpos.Ticket) { path, err := escpos.SaveTicketPNG(dir, t) if err != nil { p.Note("Error al guardar el ticket #%d: %v", t.Seq, err) return } p.Note("Ticket #%d guardado en %s", t.Seq, path) }) } info := gui.Info{BusID: usbip.BusID} if *lanAddr != "" { srv, err := lan.Listen(*lanAddr, p) if err != nil { fatal("no se pudo abrir el puerto LAN %s: %v", *lanAddr, err) } info.LAN = srv.Addr().String() p.Note("LAN: escuchando en %s (TCP RAW)", info.LAN) } if *usbAddr != "" { srv, err := usbip.Listen(*usbAddr, usbip.DeviceFromProfile(prof), p) if err != nil { fatal("no se pudo abrir el puerto USB/IP %s: %v (¿está usbipd-win usando el 3240? prueba -usbip :3241)", *usbAddr, err) } info.USBIP = srv.Addr().String() p.Note("USB/IP: escuchando en %s · conectar con: usbip attach -r -b %s", info.USBIP, usbip.BusID) } if *noGUI { stop := make(chan os.Signal, 1) signal.Notify(stop, os.Interrupt) <-stop return } gui.Run(p, info) } func fatal(format string, args ...any) { fmt.Fprintf(os.Stderr, format+"\n", args...) os.Exit(1) }