package service import ( "fmt" "strings" ) type usbPrintOpKind uint8 const ( usbOpWrite usbPrintOpKind = iota usbOpFeed usbOpQRCode usbOpCut ) type usbPrintOp struct { kind usbPrintOpKind data []byte count int qrData string qrWidth int } type usbTicketData struct { lotName, channelCode, plateNo string entryTime, slipNo, ticketNo string } var ( usbSizeNormal = []byte{GS, '!', 0x00} usbDoubleWidth = []byte{GS, '!', 0x10} usbFontA = []byte{ESC, 'M', 0} usbFontB = []byte{ESC, 'M', 1} usbDirectionOff = []byte{ESC, '{', 0} ) func buildUSBTicketLayout(data usbTicketData) []usbPrintOp { var ops []usbPrintOp write := func(data ...byte) { ops = append(ops, usbPrintOp{kind: usbOpWrite, data: append([]byte(nil), data...)}) } text := func(value string) { write(append([]byte(value), '\n')...) } feed := func(count int) { ops = append(ops, usbPrintOp{kind: usbOpFeed, count: count}) } write(ESC, '@') write(usbDirectionOff...) write(ESC, 'a', 1) write(usbFontA...) write(usbDoubleWidth...) write(BoldOnCmd...) text("Parking Ticket") write(usbSizeNormal...) write(BoldOffCmd...) write(usbFontB...) text(data.lotName) text(strings.Repeat("-", 42)) text("") text("PARK AT YOUR OWN RISK") write(ESC, 'a', 0) lotAndType := "A-General Car" if data.lotName != "" { lotAndType = data.lotName + " A-General Car" } text(lotAndType) write(usbFontA...) text("In-Time::" + data.entryTime) if data.channelCode != "" { text("InGate::" + data.channelCode) } text("Slip No::" + data.slipNo) if data.plateNo != "" { write(usbDoubleWidth...) write(BoldOnCmd...) text("Veh No::" + data.plateNo) write(usbSizeNormal...) write(BoldOffCmd...) } write(ESC, 'a', 1) feed(1) ops = append(ops, usbPrintOp{kind: usbOpQRCode, qrData: data.ticketNo, qrWidth: 12}) feed(1) // Pos_EscQrcode can change text state. Restore the settings used by the // centered payment footer before writing any more text. write(usbDirectionOff...) write(ESC, 'a', 1) write(usbFontB...) text("SCAN AND PAY WITH NEW") text("THE CANADIA BANK APP") feed(8) ops = append(ops, usbPrintOp{kind: usbOpCut}) return ops } type usbPrintDevice interface { Write([]byte) int FeedLines(int) QRCode(string, int) bool FullCut() } func executeUSBLayout(device usbPrintDevice, ops []usbPrintOp) error { for _, op := range ops { switch op.kind { case usbOpWrite: written := device.Write(op.data) if written != len(op.data) { return fmt.Errorf("USB打印短写: 写入%d/%d字节", written, len(op.data)) } case usbOpFeed: device.FeedLines(op.count) case usbOpQRCode: if !device.QRCode(op.qrData, op.qrWidth) { return fmt.Errorf("USB二维码打印失败") } case usbOpCut: device.FullCut() } } return nil }