Golang开发自动加载COM扫码枪进行一维码、二维码扫码与解码

Golang开发自动加载COM扫码枪进行一维码、二维码扫码与解码

1. 项目概述

本项目基于Golang语言开发,实现了自动检测、加载COM端口扫码枪设备,并对扫码数据进行读取、解码和处理的功能。该程序支持多种串口检测方式,自动识别不同编码格式的条码数据,并提供了高效的并发处理机制。

1.1 主要功能特点

  • 自动扫描并识别系统中的COM端口设备
  • 支持三种串口检测方式:第三方库、Windows注册表、WMI
  • 自动识别扫码枪设备(支持YJ4600和NLDC M9型号)
  • 支持UTF-8和GBK编码格式的自动检测与转换
  • 采用协程实现高效的扫码数据并发处理
  • 支持扫码数据的JSON解析与结构体转换

2. 技术栈与依赖

2.1 核心编程语言

  • Golang 1.2.24.0

2.2 主要依赖库

依赖库 用途
github.com/go-ole/go-ole Windows COM接口操作,用于WMI查询
github.com/go-ole/go-ole/oleutil OLE自动化工具库
github.com/tarm/goserial 串口通信操作
go.bug.st/serial 第三方串口检测库
golang.org/x/sys/windows/registry Windows注册表操作
golang.org/x/text/encoding/simplifiedchinese 中文编码转换

3. 系统架构与核心模块

3.1 系统架构图

scss 复制代码
┌─────────────────────────────────────────────────────┐
│                     主程序入口                       │
├────────────────┬────────────────┬───────────────────┤
│  串口检测模块   │   串口通信模块  │   数据处理模块     │
├────────────────┼────────────────┼───────────────────┤
│  getCommlist2()│   serial.OpenPort()│ readBarcodeData() │
│  getCommList() │   s.Read()      │ resolveBarcodeData() │
│ getCommListWmi()│               │ codeJsonConvertStruct() │
└────────────────┴────────────────┴───────────────────┘
          │                │                │
          └────────────────┼────────────────┘
                           ▼
                   ┌───────────────┐
                   │ 编码转换模块   │
                   ├───────────────┤
                   │  GetStrCoding()│
                   │     isUtf8()   │
                   │     isGBK()    │
                   └───────────────┘

3.2 核心模块说明

3.2.1 串口检测模块

该模块负责检测系统中所有可用的COM端口,并识别扫码枪设备。提供了三种检测方式:

  1. 第三方库检测 (getCommlist2())

    • 使用go.bug.st/serial库直接获取端口列表
    • 实现简单,但可能无法识别设备类型
  2. 注册表检测 (getCommList())

    • 通过读取Windows注册表HARDWARE\DEVICEMAP\SERIALCOMM获取端口信息
    • 支持识别特定型号的扫码枪(通过"youjie"关键词)
    • 需要管理员权限运行
  3. WMI检测 (getCommListWmi())

    • 使用Windows Management Instrumentation查询硬件信息
    • 通过Win32_PNPEntity类获取所有即插即用设备
    • 支持识别多种型号的扫码枪(YJ4600和NLDC M9)
    • 代码实现较为复杂,但功能强大
3.2.2 串口通信模块

负责与扫码枪设备建立连接并读取扫码数据:

  • 使用github.com/tarm/goserial库进行串口通信
  • 支持配置波特率等串口参数
  • 实现了持续的数据读取循环
  • 处理读取错误和异常情况
3.2.3 数据处理模块

处理从扫码枪读取到的数据:

  • readBarcodeData(): 协程函数,持续接收并处理扫码数据
  • resolveBarcodeData(): 解析条码数据,支持不同格式的条码
  • codeJsonConvertStruct(): 将JSON格式的条码数据转换为结构体
3.2.4 编码转换模块

自动识别和转换不同编码格式的数据:

  • GetStrCoding(): 自动检测数据编码格式(UTF-8、GBK或未知)
  • isUtf8(): UTF-8编码检测
  • isGBK(): GBK编码检测
  • 支持UTF-8与GBK编码之间的双向转换

4. 核心功能实现细节

4.1 串口检测实现

4.1.1 WMI检测方式详解

WMI检测是最复杂但功能最强大的检测方式,其实现步骤如下:

  1. 初始化COM接口:ole.CoInitialize(0)
  2. 创建SWbemLocator对象:oleutil.CreateObject("WbemScripting.SWbemLocator")
  3. 获取IDispatch接口:unknown.QueryInterface(ole.IID_IDispatch)
  4. 连接WMI服务:oleutil.CallMethod(wmi, "ConnectServer")
  5. 执行WMI查询:oleutil.CallMethod(service, "ExecQuery", "SELECT * FROM Win32_PNPEntity")
  6. 遍历查询结果,筛选出COM端口设备
  7. 根据设备名称识别扫码枪型号

关键代码片段:

go 复制代码
func getCommListWmi() ([]string, string) {
    // 初始化COM接口
    ole.CoInitialize(0)
    defer ole.CoUninitialize()
    
    // 创建WMI对象并执行查询
    unknown, _ := oleutil.CreateObject("WbemScripting.SWbemLocator")
    defer unknown.Release()
    wmi, _ := unknown.QueryInterface(ole.IID_IDispatch)
    defer wmi.Release()
    
    serviceRaw, _ := oleutil.CallMethod(wmi, "ConnectServer")
    service := serviceRaw.ToIDispatch()
    defer service.Release()
    
    resultRaw, _ := oleutil.CallMethod(service, "ExecQuery", "SELECT * FROM Win32_PNPEntity")
    result := resultRaw.ToIDispatch()
    defer result.Release()
    
    // 遍历结果并筛选COM端口
    // ...
}

4.2 扫码数据读取与处理

4.2.1 数据读取机制

程序通过持续循环从串口读取数据,并处理不同型号扫码枪的发送特性:

  • 支持一次性发送完整数据的扫码枪(如YJ4600)
  • 支持分多次发送数据的扫码枪(如NLDC M9)
  • 使用缓冲区拼接完整的扫码数据

关键代码片段:

go 复制代码
// 开启一个循环,持续读取扫码枪的数据
codeData := "" //用于保存每次读取到缓冲区的数据
for {
    //清空缓冲区的数据
    buf = make([]byte, 1024)
    //读取码文数据到缓冲区内
    lens, err := s.Read(buf)
    if err != nil {
        log.Println(err)
        continue
    }
    
    // 将读取到的数据追加到codeData中,处理分多次发送的情况
    x := buf[:lens]
    codeData += string(x)
    
    // 处理完整的扫码数据
    if lens > 4 {
        // 编码转换和处理
        // ...
    }
}
4.2.2 并发处理机制

程序使用Golang的协程特性实现了扫码数据的异步处理:

  • 创建一个通道用于传递扫码数据
  • 启动一个协程持续监听通道
  • 主线程读取到完整数据后发送到通道
  • 协程接收到数据后进行解析和处理

关键代码片段:

go 复制代码
// 用于接收码文的通道
receiveMessage := make(chan string)
// 开启一个协程,不断从通道内读取数据
go readBarcodeData(receiveMessage)

// 读取到完整数据后发送到通道
if codeString != "" {
    receiveMessage <- codeString
}

// 协程函数:持续读取通道内的码文数据
func readBarcodeData(message chan string) {
    for {
        select {
        case data := <-message:
            fmt.Printf("扫码时间:%v\n", time.Now().String())
            //解析码文数据
            resolveBarcodeData(data)
        }
    }
}

4.3 编码识别与转换

4.3.1 编码检测算法

程序实现了UTF-8和GBK编码的自动检测:

  1. UTF-8检测:根据UTF-8编码规则,检查字节序列是否符合格式
  2. GBK检测:检查双字节是否落在GBK编码范围内
  3. 检测顺序:先检测UTF-8,再检测GBK,确保准确性

关键代码片段:

go 复制代码
func GetStrCoding(data []byte) string {
    if isUtf8(data) == true {
        return UTF8
    } else if isGBK(data) == true {
        return GBK
    } else {
        return UNKNOWN
    }
}
4.3.2 编码转换实现

支持UTF-8与GBK编码之间的双向转换:

go 复制代码
if GetStrCoding([]byte(codeData)) == "UTF8" {
    // UTF-8转GBK再转UTF-8(处理特殊字符)
    gbkData, _ := simplifiedchinese.GB18030.NewEncoder().Bytes([]byte(codeData))
    utf8Data, _ := simplifiedchinese.GB18030.NewDecoder().Bytes(gbkData)
    codeString = string(utf8Data)
}
if GetStrCoding([]byte(codeData)) == "GBK" {
    // GBK转UTF-8
    b, _ := simplifiedchinese.GB18030.NewDecoder().Bytes([]byte(codeData))
    codeString = string(b)
}
4.3.3 运行效果
go 复制代码
(TraeAI-8) D:\vfptest [1:1] $ go run  test_com.go
蓝牙链接上的标准串行 (COM4)
蓝牙链接上的标准串行 (COM5)
Bluetooth Device (RFCOMM Protocol TDI)
本机串口列表:[蓝牙链接上的标准串行 (COM4) 蓝牙链接上的标准串行 (COM5) Bluetooth Device (RFCOMM Protocol TDI)]
扫码枪:
端口被占用
2025/12/08 13:23:17 The system cannot find the path specified.
exit status 1
(TraeAI-8) D:\vfptest [1:1] $ go run  test_com.go
YJ4600 (COM7)
strComName: YJ4600 (COM7
本机串口列表:[YJ4600 (COM7)]
扫码枪:COM7
-----------------------------------------------------------------------------------
--扫岗位证带中文
lens: 6
before convert: ������
codeData: ������
before convert: 6
coding: GBK
扫码时间:2025-12-08 13:26:26.7199849 +0800 CST m=+4.979774801
------------------------
码文: 李四▲


---------------------------------------------------------------------------------------------

--扫药品包装条码
------------------------
lens: 20
before convert: 88281800136707328258
codeData: 88281800136707328258
before convert: 20
coding: UTF8
after convert: 88281800136707328258
扫码时间:2025-12-08 13:27:05.295828 +0800 CST m=+43.555617901
------------------------
码文: 88281800136707328258

---------------------------------------------------------------------------------------------

--扫微信二维码
lens: 43
before convert: http://weixin.qq.com/r/9XUCGmDEOT1GrSR59yDn
codeData: http://weixin.qq.com/r/9XUCGmDEOT1GrSR59yDn
before convert: 43
coding: UTF8
after convert: http://weixin.qq.com/r/9XUCGmDEOT1GrSR59yDn
扫码时间:2025-12-08 13:27:23.5772834 +0800 CST m=+61.837073301
------------------------
码文: http://weixin.qq.com/r/9XUCGmDEOT1GrSR59yDn

---------------------------------------------------------------------------------------------
--扫半成品二维码带中文

lens: 380
before convert: D181��67010-AT��FD181-661-12��EM41��FLRY��0.5�����̡�690��300��15574��CC64������4����־ǿ��2016/12/21��ҹ����50��������20170102����4��X-F4��2016.11.10���۱���3��968221-1(TE)��0.5����DJ628-4.8��0.8A(ZJZ)��0.5����3.5��TE0.85����0.05mm��TE1.54����0.10mm��4.0��ZJZ1.15����0.05mm��ZJZ2.23����0.10mm��80��80������0.98��0.25��0.05+0.40��11��2/5��2��11��2/5��2������03-1-149-029�����Ǿ���
codeData: D181��67010-AT��FD181-661-12��EM41��FLRY��0.5�����̡�690��300��15574��CC64������4����־ǿ��2016/12/21��ҹ����50��������20170102����4��X-F4��2016.11.10���۱���3��968221-1(TE)��0.5����DJ628-4.8��0.8A(ZJZ)��0.5����3.5��TE0.85����0.05mm��TE1.54����0.10mm��4.0��ZJZ1.15����0.05mm��ZJZ2.23����0.10mm��80��80������0.98��0.25��0.05+0.40��11��2/5��2��11��2/5��2������03-1-149-029�����Ǿ���
before convert: 380
coding: GBK
扫码时间:2025-12-08 13:28:16.4129887 +0800 CST m=+114.672778601
------------------------
码文: D181■67010-AT■FD181-661-12■EM41■FLRY■0.5■黄绿■690■300■15574■CC64■下料4■高志强■2016/12/21■夜班■50■■■■20170102■分4■X-F4■2016.11.10■邵兵■3■968221-1(TE)■0.5■■DJ628-4.8×0.8A(ZJZ)■0.5■■3.5■TE0.85■±0.05mm■TE1.54■±0.10mm■4.0■ZJZ1.15■±0.05mm■ZJZ2.23■±0.10mm■80■80■■■0.98±0.25■0.05+0.40■11±2/5±2■11±2/5±2■■■03-1-149-029■■非军车

5. 代码优化与最佳实践

5.1 资源管理

  • 使用defer语句确保资源及时释放
  • 对WMI对象操作添加空值检查,避免空指针异常
  • 在循环中及时释放不再使用的对象

5.2 错误处理

  • 实现了完善的错误处理机制
  • 对可能失败的操作(如串口打开、数据读取)进行错误捕获和处理
  • 提供友好的错误提示信息

5.3 并发安全

  • 使用通道实现协程间的安全通信
  • 避免共享变量的直接访问,减少竞态条件

5.4 性能优化

  • 使用缓冲区拼接数据,减少字符串操作开销
  • 采用协程并发处理,提高系统响应速度
  • 实现了高效的编码检测算法

6. 使用说明

6.1 编译与运行

在项目目录下执行以下命令进行编译:

bash 复制代码
go build -o test_com.exe test_com.go

运行程序:

bash 复制代码
.	est_com.exe

6.2 端口占用处理

如果遇到端口被占用的情况,可以使用以下命令查看和终止占用进程:

  1. 查看端口占用情况:

    bash 复制代码
    netstat -aon|findstr "端口号"
  2. 查看占用端口的进程:

    bash 复制代码
    tasklist|findstr "进程ID"
  3. 终止占用进程:

    bash 复制代码
    taskkill /f /t /im 进程名称

7. 总结与展望

本项目成功实现了基于Golang的COM扫码枪自动加载与扫码解码功能,具有以下优势:

  1. 跨型号兼容:支持多种不同型号的扫码枪设备
  2. 自动适配:自动识别系统中的COM端口和扫码枪设备
  3. 编码灵活:支持多种编码格式的自动检测与转换
  4. 高效处理:采用协程实现并发数据处理,提高系统性能

未来可以进一步扩展的功能包括:

  • 支持更多类型的条码解码(如二维码、RFID等)
  • 实现图形化界面,方便用户操作
  • 增加数据持久化功能,支持扫码记录的存储和查询
  • 扩展支持Linux等其他操作系统

8. 附录

8.1 主要数据结构

go 复制代码
// 扫码数据结构体
type CodeData struct {
    Xsxh string `json:"xsxh"`
    Tzsh string `json:"tzsh"`
    Xh   string `json:"xh"`
    Clgg string `json:"clgg"`
    Ys   string `json:"ys"`
    Scrq string `json:"scrq"`
    Bc   string `json:"gc"`
    Hddh string `json:"hddh"`
    Xsgx string `json:"xsgx"`
    Bz   string `json:"gz"`
    Dz1  string `json:"dz1"`
    Ys1  string `json:"ys1"`
    Dz2  string `json:"dz2"`
    Ys2  string `json:"ys2"`
    Cpfl string `json:"cpfl"`
}

8.2 关键常量定义

go 复制代码
const (
    GBK     string = "GBK"
    UTF8    string = "UTF8"
    UNKNOWN string = "UNKNOWN"
)

相关推荐
wen-pan2 小时前
Go 语言 GMP 调度模型深度解析
开发语言·go
文攀7 小时前
Go 语言 GMP 调度模型深度解析
后端·go·编程语言
qq_233907038 小时前
GEO优化2025指南,助力企业全域适配与合规保障
go
MC皮蛋侠客15 小时前
使用 GoZero 快速构建高性能微服务项目
微服务·云原生·架构·go
139的世界真奇妙18 小时前
【Goland&IDE各种字体设置记录】
go·intellij-idea·idea
panco681201 天前
Go1.26 新特性:两全其美的 net.Dailer 方法
后端·go
仟里码1 天前
Golang GMP 实现原理
go
古城小栈2 天前
Golang Gin+Gorm :SQL注入 防护
sql·安全·go·gin
郑州光合科技余经理3 天前
同城系统海外版:一站式多语种O2O系统源码
java·开发语言·git·mysql·uni-app·go·phpstorm