zoukankan      html  css  js  c++  java
  • python实现斑马打印机网络打印

      最近一个礼拜调研了下斑马打印机怎样实现网络打印。

      缘起:

        之前实现打印方式是直接使用USB接口连接PC,使用串口通讯提供一套打印服务,在系统界面配置相关参数,即可调用打印服务;

        后来业务需求变化,现场实施并没有PC提供给打印机使用USB连接方式,因此,就开始做了这件事。

      调研后方案:

      硬件:一台Zebra ZT210斑马打印机、一个USR W610模块、一根网线

      方案一:

        后端发送ZPL指令到打印机,封装统一调用

      方案二(舍弃):

        使用本地斑马打印机驱动调用打印机,普通打印Ctrl + P调起的界面(前端实现,此种方式有几个难点:1.格式调整;2.二维码或者条码的生成,但这对于前端也不是什么难点,有实现的,相比下后端实现简单)

      方案一实现过程:

      

      打印流程:

       有人的USR W610模块实物(天线可以忽略,本次使用的网线,网口在电源线旁边):

      USR W610:充当一个TCP Server,上电后,插上网线,输入模块后面的ip(账号密码:admin/admin)就可以访问它的管理界面。若之前设置过ip,找根笔戳一下重置按钮。设置ip和端口,后端使用socket进行连接时会使用。

      USR W610后台界面:

    ·     后端核心代码:

        def post(self, request):
            """新增对象
    
            Args:
                request (rest_framework.request.Request): HTTP request
    
            Returns:
                response(rest_framework.response.Response): HTTP response.
                error_response(rest_framework.response.error_response): error_response
    
            """
            request_data = request.data
            template_name = request_data.get('template_name', '')
            if not template_name:
                return error_response(reason='模板名称不能为空',
                                      info='template_name is required',
                                      state=status.HTTP_400_BAD_REQUEST)
    
            function_name = request_data.get('function_name', '')
            if not function_name:
                return error_response(reason='功能模块名称不能为空',
                                      info='function_name is required',
                                      state=status.HTTP_400_BAD_REQUEST)
    
            is_function_name_exist = PrinterConfig.objects.filter(function_name=function_name).exists()
            if not is_function_name_exist:
                return error_response(reason='功能模块名称不存在',
                                      info='function_name is not exist',
                                      state=status.HTTP_400_BAD_REQUEST)
    
            is_template_name_exist = PrinterConfig.objects.filter(template_name=template_name).exists()
            current_dir = os.path.join(settings.BASE_DIR, 'print_template')
            is_template_name_in = template_name in os.listdir(current_dir)
            if not any([is_template_name_in, is_template_name_exist]):
                return error_response(reason='模板名称不存在',
                                      info='template_name is not exist',
                                      state=status.HTTP_400_BAD_REQUEST)
    
            file_path = os.path.join(current_dir, template_name)
            qr_code_file = open(file_path, 'r', encoding='utf-8')
            template_data = qr_code_file.read()
            template = Template(template_data)
            zpl = template.render(Context(request_data))
    
            # 携带ZPL指令向打印机发送http请求
            ip_port = PrinterConfig.objects.filter(template_name=template_name).values_list('printer_ip', 'printer_port')
            ip, port = ip_port[0][0], ip_port[0][1]
            if not all([ip, port]):
                return error_response(reason='打印配置的IP或端口未配置',
                                      info='printer ip and port must be configured',
                                      state=status.HTTP_400_BAD_REQUEST)
    
            # print_server = 'http://' + str(ip) + ':' + str(port)
            client = None
            try:
                # requests.post(print_server, data=zpl.encode('utf-8'))
                client = socket.socket(socket.AF_INET, type=socket.SOCK_STREAM)
                client.connect((ip, port))
                client.send(zpl.encode('utf-8'))
                # 打印机未连接!
            except Exception as other_except:  # pylint: disable=broad-except
                except_info = other_except.args[0]
                # except_info = other_except.args[0].args[0]
                # if except_info == 'Connection aborted.':
                if isinstance(except_info, tuple) and except_info == 'Connection aborted.':
                    return Response({'result': '打印成功,请确认'})
                else:
                    logger.error(other_except)
                    return error_response(reason='打印失败,请检查打印配置是否正确',
                                          info=str(other_except),
                                          state=status.HTTP_400_BAD_REQUEST)
            finally:
                client.close()
    
            return Response({'result': 'ok'})

      特殊说明:

      1、正如代码所表现的,打印机不会给模块响应,模块也就不会给后端响应,打印成功会抛Connection aborted.异常,实际已经打印出来。但这里为什么要请确认,是因为在TCP连接正常情况下,即使把耗材取出,比如把标签纸拿出去,也会打印成功,等换上纸后,打印任务队列对接着打印,所以这个就需要现场人员确认了。

      2、模板文件里面的ZPL指令编写,可以参考http://note.youdao.com/noteshare?id=05f00edb5f88cfe16543337f8c7f17aa&sub=77F69DD3BA7E4961A3435E9DFA7D15E5 也可以使用Zebra Designer工具进行设计生成.prn文件,文本打开即可看见ZPL指令。因为自动生成的.prn文件中ZPL指令是经过GFA加密过的,不便于使用模板语法替换,生成的内容也相比自己写的多很多。工具界面如下:

     

     .prn生成的zpl指令示例:

     自己参考ZPL指令手册写的指令示例:

    ^XA
    ^CI28
    ^CW1,E:SIMSUN.TTF
    ^MD20
    ~SD20
    ^FO142,105
    ^BQN,2,10
    ^FD  {{qr_code_print}}
    ^FS
    ^XZ

       其他说明:zpl指令中有两个值得注意的:SD   设置暗度:若打印字迹比较淡时设置            PR打印速率:若打印字迹比较稀时设置

    参考资料:

      https://www.cnblogs.com/chengeng/p/7676046.html

      https://max.book118.com/html/2018/1006/8002046103001125.shtm

      https://www.usr.cn/Down/USR-W610_instructions.pdf

       

    实践出真知~
  • 相关阅读:
    ioctl函数用法小记
    scanf函数用法小记
    printf函数用法小记
    REDIS
    lspci 虚拟机网卡对应关系
    vmware安装ubuntu " Intel VT-x 处于禁用状态"
    win10远程桌面配置
    Win10如何彻底禁用小娜?彻底禁用小娜的方法
    为什么Windows7打开项目的方式是灰的不能修改
    以下suse11.3x64可以安装pycrypto-2.6.1
  • 原文地址:https://www.cnblogs.com/NolaLi/p/14451312.html
Copyright © 2011-2022 走看看