From 016dad446fdadd7f6939ed5e7d33bc9b7aa10af8 Mon Sep 17 00:00:00 2001 From: sainw Date: Fri, 2 Oct 2026 22:35:05 +0630 Subject: [PATCH] add CheckPrinter --- build_lib.sh | 2 +- cmd/main.go | 26 ++++++++-- printer.go | 142 +++++++++++++++++++++++++-------------------------- 3 files changed, 94 insertions(+), 76 deletions(-) diff --git a/build_lib.sh b/build_lib.sh index ee70e5f..b64837a 100755 --- a/build_lib.sh +++ b/build_lib.sh @@ -1,7 +1,7 @@ #!/bin/bash APP_NAME="libgofunc" -VERSION="${1:-v0.1.11}" +VERSION="${1:-v0.1.12}" OUTPUT_DIR="../assets" BUILD_DIR="../build" diff --git a/cmd/main.go b/cmd/main.go index 280b2a5..f4362da 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -10,16 +10,34 @@ import ( ) import ( "encoding/json" + "log" + "time" "gt.mokkon.com/sainw/libgofunc" ) -//export Sum -func Sum(a, b int) int { - return a + b +func main() { + // printMultiple() + checkPrint() } -func main() { +func checkPrint() { + start := time.Now() + defer func() { + log.Printf("libgofunc.CheckPrint took %s", time.Since(start)) + }() + // printer := "tcp:192.168.100.151:9100" + // printer := "usb:/dev/usb/lp1" + + err := libgofunc.Check("usb:/dev/usb/lp1") + if err != nil { + log.Printf("check print error: %v\n", err) + return + } + log.Println("check print ok!") +} + +func printMultiple() { payload := `{ "sales": [ { "shiftId": "1001", "tran_seq": 1, "salePerson": "John Doe", "timeSec": "1717243200", "timeValue": "2026-06-01 14:30:00", "fpId": 3, "productId": 101, "product": "Diesel Premium", "price": "2500", "volume": "40", "amount": "100000", "discount_amount": "5000", "discount_percent": 5.0, "discount_money": 5000, "rule_types": "LOYALTY,FLEET", "promotion_status": true, "custom_promotion_status": false, "discount_volume": "2", "customerId": 5001, "customer_name": "ABC Logistics Pte Ltd", "vehicle_type": "Truck", "vehicle_type_extension": "10-Wheeler", "carNumber": "SGX1234A", "status": "COMPLETED", "receiptNumber": "RCP-20260601-0001", "receiptCount": 1, "mop": "CARD", "local_used_credit": 100.50, "local_credit_limit": 5000.00, "local_credit_balance": 4899.50, "local_debit_balance": 250.75, "loyalty_type": "GOLD", "points_balance": 12500, "reward_amount": 50.25, "reward_points": 500, "redeem_amount": 25.00, "redeem_points": 250, "redeem_exchange_rate": 0.1, "point_exchange_rate": 10.0, "used_credit": 100.50, "credit_limit": 10000.00, "credit_amount": 100.50, "credit_balance": 9899.50, "debit_amount": 50.25, "debit_balance": 449.75, "payment_customer_id": "PAYCUST001", "payment_customer_name": "ABC Logistics", "payment_customer_number": "+6591234567", "corp_id": "CORP001", "corp_name": "ABC Logistics Group", "card_number": "411111******1111", "upload": true, "upload_status": "SUCCESS", "send_sale_data_confirm": true, "loan_amount": 1000, "tax_percent": 9.0, "tax_status": true, "tier": 2, "dealNumber": "DL-20260601-001", "bank_name": "DBS", "bank_payment_type": "VISA", "session_id": "sess_abc123xyz", "tran_id": "txn_987654321", "qrcode_data": "SGQR|PAYNOW|ABCLOGISTICS", "fp_total": 8, "missed_sale_status": false, "opo_status": true, "ip_printer_status": true, "sale_type": "NORMAL" }, { "shiftId": "1001", "tran_seq": 1, "salePerson": "John Doe", "timeSec": "1717243200", "timeValue": "2026-06-01 14:30:00", "fpId": 3, "productId": 101, "product": "Diesel Premium", "price": "2500", "volume": "40", "amount": "100000", "discount_amount": "5000", "discount_percent": 5.0, "discount_money": 5000, "rule_types": "LOYALTY,FLEET", "promotion_status": true, "custom_promotion_status": false, "discount_volume": "2", "customerId": 5001, "customer_name": "ABC Logistics Pte Ltd", "vehicle_type": "Truck", "vehicle_type_extension": "10-Wheeler", "carNumber": "SGX1234A", "status": "COMPLETED", "receiptNumber": "RCP-20260601-0001", "receiptCount": 1, "mop": "CARD", "local_used_credit": 100.50, "local_credit_limit": 5000.00, "local_credit_balance": 4899.50, "local_debit_balance": 250.75, "loyalty_type": "GOLD", "points_balance": 12500, "reward_amount": 50.25, "reward_points": 500, "redeem_amount": 25.00, "redeem_points": 250, "redeem_exchange_rate": 0.1, "point_exchange_rate": 10.0, "used_credit": 100.50, "credit_limit": 10000.00, "credit_amount": 100.50, "credit_balance": 9899.50, "debit_amount": 50.25, "debit_balance": 449.75, "payment_customer_id": "PAYCUST001", "payment_customer_name": "ABC Logistics", "payment_customer_number": "+6591234567", "corp_id": "CORP001", "corp_name": "ABC Logistics Group", "card_number": "411111******1111", "upload": true, "upload_status": "SUCCESS", "send_sale_data_confirm": true, "loan_amount": 1000, "tax_percent": 9.0, "tax_status": true, "tier": 2, "dealNumber": "DL-20260601-001", "bank_name": "DBS", "bank_payment_type": "VISA", "session_id": "sess_abc123xyz", "tran_id": "txn_987654321", "qrcode_data": "SGQR|PAYNOW|ABCLOGISTICS", "fp_total": 8, "missed_sale_status": false, "opo_status": true, "ip_printer_status": true, "sale_type": "NORMAL" } ], "station": { "id": "1", "name": "Jurong Fuel Station", "address": "123 Boon Lay Way, Singapore 640123", "phones": "+65 6123 4567,+65 6987 6543", "code": "STN001", "money_divider": 100, "volume_divider": 1000, "check_tran_duration": 60, "fho_server_offline_duration": 300, "loyalty_backlog_duration": 1440, "token": "station-secret-token-123", "monthly_view": true, "pump_status": true, "currency": "SGD", "tank_manual_status": false, "update_price_type": "AUTO", "show_price_history": true, "old_receipt_status": false, "car_number_modification_status": true, "car_number_entry_status": 2, "shop_code": "SHOP001" }}` const temp = ` diff --git a/printer.go b/printer.go index db699ae..bfc710b 100644 --- a/printer.go +++ b/printer.go @@ -15,87 +15,54 @@ import ( "time" + "errors" + "github.com/kenshaw/escpos" ) -import ( - "errors" -) +import "io" //export PrintImg func PrintImg(printer *C.char, imagePath *C.char) *C.char { goPrinter := C.GoString(printer) goImagePath := C.GoString(imagePath) - // printer := "tcp:192.168.100.151:9100" - // printer := "usb:/dev/usb/lp1" - var w *bufio.ReadWriter - if strings.HasPrefix(goPrinter, "tcp:") { - location := strings.TrimLeft(goPrinter, "tcp:") - conn, err := net.Dial("tcp", location) - if err != nil { - log.Println("error dialing:", err.Error()) - return NewErr(err) - } - defer conn.Close() - w = bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) - } else if strings.HasPrefix(goPrinter, "usb:") { - location := strings.TrimLeft(goPrinter, "usb:") - f, err := os.OpenFile(location, os.O_RDWR, os.ModeDevice) - if err != nil { - log.Println("error OpenFile usb:", err.Error()) - return NewErr(err) - } - defer f.Close() - w = bufio.NewReadWriter(bufio.NewReader(f), bufio.NewWriter(f)) - // } else if strings.HasPrefix(goPrinter, "int:") { - // ctx := gousb.NewContext() - // // location := strings.TrimLeft(goPrinter, "int:") - // targetBus := 1 - // targetAddr := 5 - // devs, err := ctx.OpenDevices(func(desc *gousb.DeviceDesc) bool { - // return int(desc.Bus) == targetBus && int(desc.Address) == targetAddr - // }) - // if err != nil || len(devs) == 0 { - // log.Fatal("Could not find or open the device") - // } - // dev := devs[0] - // defer dev.Close() - // dev.SetAutoDetach(true) - - // // 2. Claim the default interface (usually 0 for printers) - // // Note: This may require detaching the kernel driver on Linux - // intf, done, err := dev.DefaultInterface() - // if err != nil { - // log.Fatalf("Failed to claim interface: %v", err) - // } - // defer done() - - // // 3. Open the Bulk Output Endpoint (usually endpoint #1 or #2) - // // You may need to inspect desc.Endpoints to find the correct Bulk Out ID - // out, err = intf.OutEndpoint(1) - // if err != nil { - // log.Fatalf("Failed to open OUT endpoint: %v", err) - // } - // // w = bufio.NewReadWriter(bufio.NewReader(outPort), bufio.NewWriter(f)) - // rw := &USBReadWriter{out: out} - // reader := bufio.NewReader(rw) - // writer := bufio.NewWriter(rw) - // w = bufio.NewReadWriter(reader, writer) - } else { - return NewErr(errors.New("invalid printer")) + err := Print(goPrinter, goImagePath) + if err != nil { + return NewErr(err) } + return NewOk(nil) +} + +//export CheckPrinter +func CheckPrinter(printer *C.char) *C.char { + goPrinter := C.GoString(printer) + err := Check(goPrinter) + if err != nil { + return NewErr(err) + } + return NewOk(nil) +} + +func Print(printer, imagePath string) error { + conn, err := connect(printer) + if err != nil { + return err + } + defer conn.Close() + w := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) + prt := escpos.New(w) prt.Init() prt.SetSmooth(1) prt.SetAlign("left") - imgBytes, err := imgData(goImagePath) + imgBytes, err := imgData(imagePath) if err != nil { - return NewErr(err) + return err } - err = WriteChunk(w, prt, imgBytes) + err = writeChunk(w, prt, imgBytes) if err != nil { - return NewErr(err) + return err } time.Sleep(500 * time.Millisecond) w.Flush() @@ -105,17 +72,50 @@ func PrintImg(printer *C.char, imagePath *C.char) *C.char { prt.End() w.Flush() time.Sleep(1 * time.Second) - return NewOk(nil) + return nil } -func Print(printer, imagePath string) string { - result := PrintImg(C.CString(printer), C.CString(imagePath)) - r := C.GoString(result) - return r +func Check(printer string) error { + conn, err := connect(printer) + if err != nil { + return err + } + defer conn.Close() + + var w *bufio.ReadWriter + w = bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) + prt := escpos.New(w) + + prt.Init() + prt.SetSmooth(1) + prt.SetAlign("left") + time.Sleep(100 * time.Millisecond) + return w.Flush() } -// WriteChunk breaks the large byte array into smaller chunks -func WriteChunk(w *bufio.ReadWriter, prt *escpos.Escpos, data []byte) error { +func connect(printer string) (io.ReadWriteCloser, error) { + if strings.HasPrefix(printer, "tcp:") { + location := strings.TrimLeft(printer, "tcp:") + conn, err := net.Dial("tcp", location) + if err != nil { + log.Println("error net.Dial tcp:", err.Error()) + return nil, err + } + return conn, nil + } else if strings.HasPrefix(printer, "usb:") { + location := strings.TrimLeft(printer, "usb:") + f, err := os.OpenFile(location, os.O_RDWR, os.ModeDevice) + if err != nil { + log.Println("error os.OpenFile usb:", err.Error()) + return nil, err + } + return f, nil + } + return nil, errors.New("invalid printer") +} + +// writeChunk breaks the large byte array into smaller chunks +func writeChunk(w *bufio.ReadWriter, prt *escpos.Escpos, data []byte) error { chunkSize := 1024 // 1 KB chunks work best for network printers for i := 0; i < len(data); i += chunkSize { end := min(i+chunkSize, len(data))