package service import ( "fmt" "os" "syscall" "unsafe" "github.com/tarm/serial" ) // SerialPrinter 串口打印机 type SerialPrinter struct { Port *serial.Port } func NewSerialPrinter(portName string, baudRate int) (*SerialPrinter, error) { if baudRate <= 0 { baudRate = 9600 } if len(portName) < 3 || portName[:3] != "COM" { return nil, fmt.Errorf("非串口设备: %s", portName) } c := &serial.Config{Name: portName, Baud: baudRate} port, err := serial.OpenPort(c) if err != nil { return nil, fmt.Errorf("打开串口失败 %s: %w", portName, err) } return &SerialPrinter{Port: port}, nil } func (p *SerialPrinter) Write(data []byte) error { _, err := p.Port.Write(data) return err } func (p *SerialPrinter) Close() error { return p.Port.Close() } // === Windows RAW 打印机(WritePrinter API)=== var ( winspool = syscall.NewLazyDLL("winspool.drv") procOpenPrinter = winspool.NewProc("OpenPrinterW") procClosePrinter = winspool.NewProc("ClosePrinter") procStartDoc = winspool.NewProc("StartDocPrinterW") procStartPage = winspool.NewProc("StartPagePrinter") procWritePrinter = winspool.NewProc("WritePrinter") procEndPage = winspool.NewProc("EndPagePrinter") procEndDoc = winspool.NewProc("EndDocPrinter") ) type DOC_INFO_1 struct { pDocName *uint16 pOutputFile *uint16 pDataType *uint16 } func PrintRaw(printerName string, data []byte) error { namePtr, _ := syscall.UTF16PtrFromString(printerName) var handle syscall.Handle ret, _, _ := procOpenPrinter.Call(uintptr(unsafe.Pointer(namePtr)), uintptr(unsafe.Pointer(&handle)), 0) if ret == 0 { return fmt.Errorf("OpenPrinter 失败: %s", printerName) } defer procClosePrinter.Call(uintptr(handle)) docName, _ := syscall.UTF16PtrFromString("Parking Ticket") dataType, _ := syscall.UTF16PtrFromString("RAW") di := DOC_INFO_1{pDocName: docName, pDataType: dataType} procStartDoc.Call(uintptr(handle), 1, uintptr(unsafe.Pointer(&di))) procStartPage.Call(uintptr(handle)) var written uint32 procWritePrinter.Call(uintptr(handle), uintptr(unsafe.Pointer(&data[0])), uintptr(len(data)), uintptr(unsafe.Pointer(&written))) procEndPage.Call(uintptr(handle)) procEndDoc.Call(uintptr(handle)) return nil } var _ = os.Stderr // keep import