python使用escpos库进行usb打印机通信(按usb序列号选择打印机)

之前写了一篇“windows下python实现usb收发通信”的文章,是使用底层库来实现python与usb的收发通信;如果你的热敏打印机支持标准的ESC/POS指令的话是可以使用python-escpos这个库(号称python下的打印机神器)进行打印机操作,这个库虽然连接、控制、打印都相对比较简单,但是如果相同型号的打印机连接到同一个电脑设备上,那么它可能只会随机地选择其中一台打印机打印,无法指定打印机!这也是为什么有了之前那边使用python直接与usb进行通信的文章。后来又研究了下escpos这个库的源码,发现其实可以对usb的open方法进行改造就可以实现通过usb设备序列号来区分相同型号的打印机了(有些打印机厂家可能usb序列号没有或者都一样,那么最好建议问厂家能不能给个改写序列号的软件/固件,或者是提供一个版本号查询方法通过版本号来区分打印机设备)

一、准备工作

1、我这里是python3.12(正常python3.x应该都行)

2、安装python-escpos,如果运行时提示缺少包那么就把缺失的安装一遍

pip install python-escpos

3、找到打印机的厂商ID和产品ID的设备(在设备管理器里面可以看到,我上面提到的文章里也有介绍,不会的百度)

4、找到你打印机的设备序列号,可以网上找下怎么查询usb序列号,也可以使用我下面提供的源码来进行查询

二、改造后的源码

注意设备厂商ID和产品ID要选对,否则匹配不上,另外设备序列号如果不知道怎么获取可以随便填写赋值serial_number,程序运行的时候会打印已知的序列号,打印出来后复制并替换serial_number值,然后重新再运行一遍程序即可。

import logging
from typing import Optional, Type

from escpos.printer.usb import dependency_usb
from escpos.printer import Usb
import usb.core
import usb.util
from escpos.exceptions import DeviceNotFoundError, USBNotFoundError

# 重写usb连接方式调用
class CustomUSBPrinter(Usb):
    def __init__(self, vendor_id, product_id, serial_number=None, *args, **kwargs):
        self.serial_number = serial_number
        self.idVendor= vendor_id
        self.idProduct = product_id
        try:
            super().__init__(idVendor=vendor_id, idProduct=product_id, *args, **kwargs)
        except (USBNotFoundError, usb.core.USBError):
            # 静默捕获异常,不退出程序
            print("USB device not found or error")
            pass
    @dependency_usb
    def open(self, raise_not_found: bool = True) -> None:
        """重写 open 方法,支持根据序列号筛选设备"""
        # 查找所有匹配厂商ID和产品ID的设备
        #print('重写的方法usb')

        if self._device:
            self.close()

        # Open device
        try:
            if self.serial_number: #需要按序列号来查找设备
                devs = usb.core.find(find_all=True, idVendor=self.idVendor, idProduct=self.idProduct)
                for dev in devs:
                    try:
                        current_serial = usb.util.get_string(dev, dev.iSerialNumber)
                        print(f'已发现usb设备序列号:{current_serial}')  # 如果列出发现的设备对应的序列号,可以复制后续使用
                        if current_serial == self.serial_number:
                            self.device = dev
                            break # 找第一个匹配的
                    except (usb.USBError, UnicodeDecodeError):
                        print('发生了某些usb设备错误')
                        continue
            else: # 原逻辑
                self.device: Optional[Type[usb.core.Device]] = usb.core.find(
                    **self.usb_args
                )
                assert self.device, USBNotFoundError(
                    f"Device {tuple(self.usb_args.values())} not found"
                    + " or cable not plugged in."
                )
            # 配置USB连接
            self._check_driver()
            self._configure_usb()
        except (AssertionError, usb.core.USBError) as e:
            # Raise exception or log error and cancel
            self.device = None
            if raise_not_found:
                raise DeviceNotFoundError(
                    f"Unable to open USB printer on {tuple(self.usb_args.values())}:"
                    + f"n{e}"
                )
            else:
                logging.error("USB device %s not found", tuple(self.usb_args.values()))
                return
        logging.info("USB printer enabled")

# 下面是正式使用…………
# 示例:连接指定厂商ID、产品ID和序列号的设备
idVendor = 0x5a5a
idProduct = 0x8009
serial_number= '206035763031' # 序列号,如果已知idVendor、idProduct 序列号可以随便填,程序会打印出来,然后复制过来替换本序列号
in_ep= 0x81 # python库默认的是0x82 根据实际的来
out_ep= 0x01 # 有的是0x02


try:
    # 尝试连接打印机
    printer = CustomUSBPrinter(vendor_id=idVendor,product_id=idProduct,serial_number=serial_number,in_ep=in_ep,out_ep=out_ep)
    #printer = CustomUSBPrinter(vendor_id=idVendor, product_id=idProduct, in_ep=in_ep, out_ep=out_ep)
    connected = printer.device is not None  # 确认设备存在
except (DeviceNotFoundError, usb.core.USBError):
    printer = None
    connected = False

# 检查连接状态
if connected:
    # 正常连接成功,还应该检测打印机状态; 部分打印机状态异常时也能接收到并缓存打印指令,打印机不断电情况下修复错误后会打印缓存中的指令!
    print("USB 打印机已连接")
    printer.text("--测试打印n")
    printer.qr(content='https://www.baidu.com',size=6) # 二维码
    printer.barcode('6935103100088', 'EAN13', 64, 2, '', '') # 条码
    img_src = "ticket_at.png"
    printer.image(img_src, impl="bitImageRaster")

    printer.close()
else:
    print("USB 打印机未连接")

三、提示

充分利用好AI,问问文心一言、DeepSeek,他们也能解决很多代码片段问题!

基于互联网精神,在注明出处的前提下本站文章可自由转载!

本文链接:https://ranjuan.cn/python-escpos-usb-serialnum-printer/

赞赏

微信赞赏支付宝赞赏

发表评论