|
@@ -2,16 +2,29 @@ package service
|
|
|
|
|
|
|
|
import (
|
|
import (
|
|
|
"fmt"
|
|
"fmt"
|
|
|
|
|
+ "os"
|
|
|
|
|
+ "syscall"
|
|
|
|
|
+
|
|
|
"github.com/tarm/serial"
|
|
"github.com/tarm/serial"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+// SerialPrinter 通用打印机接口(串口或 Windows USB)
|
|
|
|
|
+type Printer interface {
|
|
|
|
|
+ Write(data []byte) error
|
|
|
|
|
+ Close() error
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
type SerialPrinter struct {
|
|
type SerialPrinter struct {
|
|
|
Port *serial.Port
|
|
Port *serial.Port
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func NewSerialPrinter(portName string, baudRate int) (*SerialPrinter, error) {
|
|
func NewSerialPrinter(portName string, baudRate int) (*SerialPrinter, error) {
|
|
|
if baudRate <= 0 {
|
|
if baudRate <= 0 {
|
|
|
- baudRate = 9600 // EMD807 factory default
|
|
|
|
|
|
|
+ baudRate = 9600
|
|
|
|
|
+ }
|
|
|
|
|
+ // 非 COM 端口 → 尝试 Windows 打印机路径
|
|
|
|
|
+ if len(portName) >= 3 && portName[:3] != "COM" {
|
|
|
|
|
+ return nil, fmt.Errorf("非串口设备,请使用 USB 驱动安装虚拟 COM 口,或连接真实 COM 口")
|
|
|
}
|
|
}
|
|
|
c := &serial.Config{Name: portName, Baud: baudRate}
|
|
c := &serial.Config{Name: portName, Baud: baudRate}
|
|
|
port, err := serial.OpenPort(c)
|
|
port, err := serial.OpenPort(c)
|
|
@@ -29,3 +42,48 @@ func (p *SerialPrinter) Write(data []byte) error {
|
|
|
func (p *SerialPrinter) Close() error {
|
|
func (p *SerialPrinter) Close() error {
|
|
|
return p.Port.Close()
|
|
return p.Port.Close()
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+// USBPrinter Windows USB 打印机(原生 API 发送 RAW 数据)
|
|
|
|
|
+type USBPrinter struct {
|
|
|
|
|
+ handle syscall.Handle
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func NewUSBPrinter(printerName string) (*USBPrinter, error) {
|
|
|
|
|
+ path := fmt.Sprintf("\\\\.\\%s", printerName)
|
|
|
|
|
+ pathPtr, err := syscall.UTF16PtrFromString(path)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return nil, err
|
|
|
|
|
+ }
|
|
|
|
|
+ handle, err := syscall.CreateFile(
|
|
|
|
|
+ pathPtr,
|
|
|
|
|
+ syscall.GENERIC_WRITE,
|
|
|
|
|
+ syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE,
|
|
|
|
|
+ nil,
|
|
|
|
|
+ syscall.OPEN_EXISTING,
|
|
|
|
|
+ syscall.FILE_ATTRIBUTE_NORMAL,
|
|
|
|
|
+ 0,
|
|
|
|
|
+ )
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ // 尝试通过 UNC 路径
|
|
|
|
|
+ uncPath := fmt.Sprintf("\\127.0.0.1\\%s", printerName)
|
|
|
|
|
+ uncPtr, _ := syscall.UTF16PtrFromString(uncPath)
|
|
|
|
|
+ handle, err = syscall.CreateFile(uncPtr, syscall.GENERIC_WRITE,
|
|
|
|
|
+ syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, nil,
|
|
|
|
|
+ syscall.OPEN_EXISTING, 0, 0)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return nil, fmt.Errorf("无法打开打印机 %s: %w", printerName, err)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return &USBPrinter{handle: handle}, nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (p *USBPrinter) Write(data []byte) error {
|
|
|
|
|
+ var written uint32
|
|
|
|
|
+ return syscall.WriteFile(p.handle, data, &written, nil)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (p *USBPrinter) Close() error {
|
|
|
|
|
+ return syscall.CloseHandle(p.handle)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+var _ = os.Stderr // keep os import
|