| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- package service
- import (
- "fmt"
- "os"
- "path/filepath"
- "syscall"
- "unsafe"
- )
- // CSN Printer SDK — Go wrapper for CsnPrinterLibs.dll (x64)
- // FindCsnDllPath 按优先级探测 CsnPrinterLibs.dll 位置:
- // 1. exe 同目录(生产环境:build/bin/ 与 smart-parking.exe 一起分发)
- // 2. 当前工作目录
- // 3. 项目相对路径(wails dev 时 cwd 为 lc_garage/)
- // 4. 开发机原始绝对路径(兜底)
- func FindCsnDllPath() string {
- exePath, _ := os.Executable()
- candidates := []string{
- filepath.Join(filepath.Dir(exePath), "CsnPrinterLibs.dll"),
- "CsnPrinterLibs.dll",
- "build/bin/CsnPrinterLibs.dll",
- `D:\lq\资料\停车场 道闸 车牌识别 收费机\票机自制\打印机\EMD807嵌入式热敏票据打印模组\5、SDK指令集\Win_SDK_Demo_2023_08_14\Win_SDK_Demo_2023_08_14\lib\x64\CsnPrinterLibs.dll`,
- }
- for _, p := range candidates {
- if _, err := os.Stat(p); err == nil {
- return p
- }
- }
- return candidates[0]
- }
- var csnDll *syscall.LazyDLL
- // parseCSNPortNames parses the SDK's double-NUL-terminated port list.
- // Port_EnumUSB and Port_EnumPRN return the number of entries, not the byte length.
- func parseCSNPortNames(buffer []byte) []string {
- var names []string
- for start := 0; start < len(buffer); {
- end := start
- for end < len(buffer) && buffer[end] != 0 {
- end++
- }
- if end == start {
- break
- }
- names = append(names, string(buffer[start:end]))
- start = end + 1
- }
- return names
- }
- func csnEnumPortNames(procName string) []string {
- if csnDll == nil {
- return nil
- }
- buf := make([]byte, 256)
- ret, _, _ := csnDll.NewProc(procName).Call(uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)))
- if ret == 0 {
- return nil
- }
- return parseCSNPortNames(buf)
- }
- func InitCSN(dllPath string) error {
- csnDll = syscall.NewLazyDLL(dllPath)
- // Test load
- if err := csnDll.Load(); err != nil {
- return fmt.Errorf("加载 CsnPrinterLibs.dll 失败: %w", err)
- }
- return nil
- }
- // === Port functions ===
- func Csn_EnumUSB() string {
- names := csnEnumPortNames("Port_EnumUSB")
- if len(names) == 0 {
- return ""
- }
- return names[0]
- }
- func Csn_EnumPRN() string {
- names := csnEnumPortNames("Port_EnumPRN")
- if len(names) == 0 {
- return ""
- }
- return names[0]
- }
- func Csn_EnumUSBNames() []string {
- return csnEnumPortNames("Port_EnumUSB")
- }
- func Csn_EnumPRNNames() []string {
- return csnEnumPortNames("Port_EnumPRN")
- }
- func Csn_OpenUSB(name string) (uintptr, error) {
- if csnDll == nil {
- return 0, fmt.Errorf("DLL 未加载")
- }
- nameBytes := append([]byte(name), 0)
- ret, _, _ := csnDll.NewProc("Port_OpenUSBIO").Call(
- uintptr(unsafe.Pointer(&nameBytes[0])))
- if ret == 0 {
- return 0, fmt.Errorf("打开 USB 打印机失败: %s", name)
- }
- return ret, nil
- }
- func Csn_OpenPRN(name string) (uintptr, error) {
- if csnDll == nil {
- return 0, fmt.Errorf("DLL 未加载")
- }
- nameBytes := append([]byte(name), 0)
- ret, _, _ := csnDll.NewProc("Port_OpenPRNIO").Call(
- uintptr(unsafe.Pointer(&nameBytes[0])))
- if ret == 0 {
- return 0, fmt.Errorf("打开 Windows 打印机失败: %s", name)
- }
- return ret, nil
- }
- func Csn_SetPort(handle uintptr) {
- if csnDll != nil && handle != 0 {
- csnDll.NewProc("Port_SetPort").Call(handle)
- }
- }
- func csn_Close(handle uintptr) {
- if csnDll != nil && handle != 0 {
- csnDll.NewProc("Port_ClosePort").Call(handle)
- }
- }
- // Csn_Close 关闭调试接口或外部适配层打开的 CSN 端口。
- func Csn_Close(handle uintptr) {
- csn_Close(handle)
- }
- // === Print functions ===
- func csn_Reset() {
- if csnDll != nil {
- csnDll.NewProc("Pos_Reset").Call()
- }
- }
- func csn_FeedLine() {
- if csnDll != nil {
- csnDll.NewProc("Pos_FeedLine").Call()
- }
- }
- func csn_FeedLines(n int) {
- if csnDll != nil {
- csnDll.NewProc("Pos_Feed_N_Line").Call(uintptr(n))
- }
- }
- func csn_Align(value int) { // 0=左, 1=中, 2=右
- if csnDll != nil {
- csnDll.NewProc("Pos_Align").Call(uintptr(value))
- }
- }
- func csn_FullCut() {
- if csnDll != nil {
- csnDll.NewProc("Pos_FullCutPaper").Call()
- }
- }
- // WriteData 直接发送 RAW 字节到当前激活的打印机端口
- func Csn_WriteData(data []byte) int {
- if csnDll == nil {
- return 0
- }
- ret, _, _ := csnDll.NewProc("WriteData").Call(
- uintptr(unsafe.Pointer(&data[0])),
- uintptr(len(data)),
- 3000) // timeout 3s
- return int(ret)
- }
- // csn_Text 打印一行文字
- // nOrgx: -1=左对齐, -2=居中, -3=右对齐
- func csn_Text(text string, widthTimes, heightTimes, fontType, fontStyle, nOrgx int) {
- if csnDll == nil {
- return
- }
- // Pos_Text(const wchar_t *prnText, int nLan, int nOrgx, int nWidthTimes, int nHeightTimes, int FontType, int nFontStyle)
- wstr, _ := syscall.UTF16FromString(text)
- csnDll.NewProc("Pos_Text").Call(
- uintptr(unsafe.Pointer(&wstr[0])),
- 0, // nLan: 0=GBK
- uintptr(nOrgx),
- uintptr(widthTimes),
- uintptr(heightTimes),
- uintptr(fontType),
- uintptr(fontStyle))
- csn_FeedLine()
- }
- func csn_QRCode(data string, width int) bool {
- if csnDll == nil {
- return false
- }
- wstr, _ := syscall.UTF16FromString(data)
- ret, _, _ := csnDll.NewProc("Pos_EscQrcode").Call(
- uintptr(unsafe.Pointer(&wstr[0])),
- uintptr(width), 4) // nWidth, nErrLevel=4
- return ret != 0
- }
- func csn_Barcode(data string, barcodeType int, unitWidth, unitHeight, fontStyle, fontPos int) {
- if csnDll == nil {
- return
- }
- dataBytes := append([]byte(data), 0)
- csnDll.NewProc("Pos_Barcode").Call(
- uintptr(unsafe.Pointer(&dataBytes[0])),
- uintptr(barcodeType), 0, uintptr(unitWidth), uintptr(unitHeight),
- uintptr(fontStyle), uintptr(fontPos))
- }
|