【斑马打印机】web前端页面通过BrowserPrint API连接斑马打印机进行RFID条形码贴纸打印
web前端页面通过BrowserPrint API连接斑马打印机进行RFID条形码贴纸打印
在现代物流、仓储和零售行业中,RFID和二维码技术发挥着至关重要的作用。这些技术不仅提高了效率,还增强了追踪和管理的能力。本文将介绍如何使用JavaScript和斑马打印机的BrowserPrint API来打印RFID二维码贴纸。
1. BrowserPrint API 简介
BrowserPrint是斑马技术公司提供的一个JavaScript库,它允许网页应用直接与连接到客户端计算机上的斑马打印机进行交互。这意味着开发者可以在不需要安装额外软件的情况下,直接从网页应用中发送打印任务到斑马打印机。
2. 环境设置
要使用BrowserPrint API,首先需要确保斑马打印机正确连接到计算机,并且用户的系统上已安装BrowserPrint应用程序。此应用程序作为一个服务运行,允许通过本地网络接口与打印机通信。
本例使用的是zebra-browser-print-windows-v131445.exe作为驱动。
安装后运行程序,驱动会通过串口查询到已经连接的斑马打印机,并启动一个本地服务与之通信。
3. 打印机初始化
在JavaScript代码中,首先需要初始化BrowserPrint API,并搜索可用的打印设备。以下是初始化打印机并检索连接的打印机列表的代码段:
BrowserPrint.getLocalDevices(devices => {this.printers = devices.printer.filter(device => device.deviceType === 'printer');if (!this.printers || !this.printers.length) {this.$message.error('没有可用的打印机,请检查驱动或USB连接!');}
}, error => {this.$message.error('无法找到打印机,请检查驱动或USB连接!');
});
4. 构建ZPL指令
ZPL(Zebra Programming Language)是斑马打印机使用的命令语言,用于定义打印标签的布局和内容。在我们的示例中,我们构建了一个ZPL字符串,用于设置标签的大小、位置和内容,包括二维码和RFID数据。
let index = 1;let zpl = '^XA'let x = baseX;let y = baseY;for (let item of tableData) {if (item.h) {zpl += ' ^CI28 ^FO' + (x - spacingX * 2) + ',' + y + '^A@R,32,32,E:SIMSUN.TTF ^FB160,8,,J, ^FD' + (item.lable || '') + ':' + '^FS ';zpl += ' ^CI28 ^FO' + (x - spacingX * 2) + ',' + (y + 160) + '^A@R,32,32,E:SIMSUN.TTF ^FB330,8,,J, ^FD' + (item.value || '') + '^FS ';} else {zpl += ' ^CI28 ^FO' + x + ',' + y + '^A@R,32,32,E:SIMSUN.TTF ^FB160,2,,J, ^FD' + (item.lable || '') + ':' + '^FS ';zpl += ' ^CI28 ^FO' + x + ',' + (y + 160) + '^A@R,32,32,E:SIMSUN.TTF ^FB330,2,,J, ^FD' + (item.value || '') + '^FS ';}if (index === 3) {x -= spacingX;y = baseY;index = 1;} else {index++;y += spacingY;}}zpl += ' ^FO' + baseY + ',' + (baseY + (spacingY * 0.9)) + '^BY3 ^BCR,100,Y,N,N ^FD' + (tableData.find(item => item.lable === '条码号').value || '') + '^FS 'let bdbh = tableData.find(item => item.lable === '磅单编号').value || '';if (bdbh.length > 12) {this.$message.error('磅单编号长度大于12,写入RFID将不正确!')}function stringToHexAscii (input) {let hexAscii = '';for (let i = 0; i < input.length; i++) {const charCode = input.charCodeAt(i);const hexValue = charCode.toString(16).padStart(2, '0');hexAscii += hexValue.toUpperCase();}return hexAscii;}bdbh = stringToHexAscii(bdbh)zpl += '^RFW,H^FD' + bdbh + 'FFFFFFFFFFFFFFFFFFFFFFFF' + '^FS'zpl += '^XZ'
构建ZPL指令详解
ZPL(Zebra Programming Language)是斑马打印机专用的一种命令语言,用于控制标签的打印格式和内容。在构建ZPL指令时,每个指令都有特定的功能,用于定义打印内容的布局、样式和特性。下面将详细介绍示例中使用的主要ZPL指令及其意义:
1. ^XA
和 ^XZ
^XA
:这是每个ZPL脚本的开始指令,表示开始一条新的标签格式指令。^XZ
:这是结束指令,表示标签格式指令结束。在这之后的指令将不会被执行,直到遇到下一个^XA
。
2. ^FO
(Field Origin)
^FOx,y
:设置接下来的打印字段的起始位置,其中[x](file:///d%3A/ch/template-builder/print.js#51%2C231-51%2C231)和[y](file:///d%3A/ch/template-builder/print.js#197%2C11-197%2C11)是横纵坐标。这个指令用于定位条码、文本或图像在标签上的具体位置。
3. ^A
(Font Specification)
^A@R,32,32,E:SIMSUN.TTF
:这个指令用于设置字体。[@R](file:///d%3A/ch/template-builder/print.js#200%2C67-200%2C67)表示字体旋转角度,[32,32](file:///d%3A/ch/template-builder/print.js#200%2C70-200%2C70)分别是字体的宽度和高度,E:SIMSUN.TTF
指定使用的字体文件。
4. ^FB
(Field Block)
^FB160,2,,J,
:这个指令用于定义一个文本字段的属性。[160](file:///d%3A/ch/template-builder/print.js#201%2C65-201%2C65)是字段宽度,[2](file:///d%3A/ch/template-builder/print.js#14%2C136-14%2C136)是最大行数,[J](file:///d%3A/ch/template-builder/print.js#200%2C99-200%2C99)表示文本的对齐方式(此处为居中对齐)。
5. ^FD
(Field Data)
^FDtext^FS
:这个指令用于定义字段的内容。[text](file:///d%3A/ch/template-builder/print.js#23%2C31-23%2C31)是要打印的文本。^FS
(Field Separator)标记字段数据的结束。
6. ^BY
(Bar Code Field Default)
^BY3
:这个指令用于设置条码的默认宽度因子,[3](file:///d%3A/ch/template-builder/print.js#36%2C172-36%2C172)表示条码宽度为标准宽度的三倍。
7. ^BC
(Code 128 Bar Code)
^BCR,100,Y,N,N
:这个指令用于打印Code 128条码。[R](file:///d%3A/ch/template-builder/print.js#200%2C68-200%2C68)表示条码旋转角度,[100](file:///d%3A/ch/template-builder/print.js#164%2C22-164%2C22)是条码的高度,后面的[Y](file:///d%3A/ch/template-builder/print.js#215%2C81-215%2C81)和[N](file:///d%3A/ch/template-builder/print.js#215%2C83-215%2C83)分别表示是否打印解释行(条码下的数字或字母)和是否在条码下方打印解释行。
8. ^RFW,H^FD
(RFID Encoding)
^RFW,H^FDdata^FS
:这个指令用于向RFID标签写入数据。[H](file:///d%3A/ch/template-builder/print.js#230%2C20-230%2C20)指定数据的写入模式(此处为十六进制),[data](file:///d%3A/ch/template-builder/print.js#18%2C11-18%2C11)是要写入的数据。
通过这些指令的组合,可以精确地控制斑马打印机打印出的标签的每一个细节,从简单的文本到复杂的条码和RFID数据,都可以通过ZPL指令灵活配置。
5. 发送打印任务
构建完ZPL指令后,可以使用BrowserPrint API将其发送到打印机进行打印:
printer.send(zpl, _ => {this.$message.success('开始打印!');callback && callback();
}, error => {this.$message.error('打印失败,请确认打印机状态!');
});
6. 错误处理和用户反馈
在整个过程中,代码通过Vue.js的$message
方法提供了用户反馈,包括成功消息和错误消息。这确保了用户能够了解打印过程中发生的任何问题,并采取相应的措施。
7.完整代码
以下代码可以作为一个vue项目的混入直接使用,你可以根据自己的实际情况对参数进行调整
let finishedFunction = null;
let response = null;
var $jscomp = $jscomp || {}; $jscomp.scope = {}; $jscomp.checkStringArgs = function (b, h, c) { if (null == b) throw new TypeError("The 'this' value for String.prototype." + c + " must not be null or undefined"); if (h instanceof RegExp) throw new TypeError("First argument to String.prototype." + c + " must not be a regular expression"); return b + "" }; $jscomp.ASSUME_ES5 = !1; $jscomp.ASSUME_NO_NATIVE_MAP = !1; $jscomp.ASSUME_NO_NATIVE_SET = !1;
$jscomp.defineProperty = $jscomp.ASSUME_ES5 || "function" == typeof Object.defineProperties ? Object.defineProperty : function (b, h, c) { b != Array.prototype && b != Object.prototype && (b[h] = c.value) }; $jscomp.getGlobal = function (b) { return "undefined" != typeof window && window === b ? b : "undefined" != typeof global && null != global ? global : b }; $jscomp.global = $jscomp.getGlobal(this);
$jscomp.polyfill = function (b, h, c, e) { if (h) { c = $jscomp.global; b = b.split("."); for (e = 0; e < b.length - 1; e++) { var k = b[e]; k in c || (c[k] = {}); c = c[k] } b = b[b.length - 1]; e = c[b]; h = h(e); h != e && null != h && $jscomp.defineProperty(c, b, { configurable: !0, writable: !0, value: h }) } };
$jscomp.polyfill("String.prototype.startsWith", function (b) { return b ? b : function (b, c) { var e = $jscomp.checkStringArgs(this, b, "startsWith"); b += ""; var h = e.length, p = b.length; c = Math.max(0, Math.min(c | 0, e.length)); for (var l = 0; l < p && c < h;)if (e[c++] != b[l++]) return !1; return l >= p } }, "es6", "es3");
var BrowserPrint = function () {function b (a, b) { var d = new XMLHttpRequest; "withCredentials" in d ? d.open(a, b, !0) : "undefined" != typeof XDomainRequest ? (d = new XDomainRequest, d.open(a, b)) : d = null; return d } function h (a, b, d) { void 0 === b && (b = e.defaultSuccessCallback); void 0 === d && (d = e.defaultErrorCallback); return c(a, b, d) } function c (a, b, d) {a.onreadystatechange = function () {a.readyState === XMLHttpRequest.DONE && 200 === a.status ? "" === a.responseType ? b(a.responseText) : b(a.response) : a.readyState === XMLHttpRequest.DONE && (d ? d(a.response) :console.log("error occurred with no errorCallback set."))}; return a} var e = {}, k = {}, p = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); navigator.userAgent.indexOf("Trident/7.0"); var l = "http://127.0.0.1:9100/"; p && "https:" === location.protocol && (l = "https://127.0.0.1:9101/"); e.Device = function (a) {var m = this; this.name = a.name; this.deviceType = a.deviceType; this.connection = a.connection; this.uid = a.uid; this.version = 2; this.provider = a.provider; this.manufacturer = a.manufacturer; this.readRetries = "bluetooth" ===this.connection ? 1 : 0; this.sendErrorCallback = function (d) { }; this.sendFinishedCallback = function (d) { }; this.readErrorCallback = function (d) { }; this.readFinishedCallback = function (d) { }; this.send = function (d, a, f) {var g = b("POST", l + "write"); g && (void 0 !== m && (void 0 === a && (a = m.sendFinishedCallback), void 0 === f && (f = m.sendErrorCallback)), c(g, a, f), g.send(JSON.stringify({device: { name: this.name, uid: this.uid, connection: this.connection, deviceType: this.deviceType, version: this.version, provider: this.provider, manufacturer: this.manufacturer },data: d})))}; this.sendUrl = function (d, a, f, e) { var g = b("POST", l + "write"); g && (c(m, g, a, f), d = { device: { name: this.name, uid: this.uid, connection: this.connection, deviceType: this.deviceType, version: this.version, provider: this.provider, manufacturer: this.manufacturer }, url: d }, null != e && void 0 != e && (d.options = e), g.send(JSON.stringify(d))) }; this.sendFile = function (d, a, f) {if ("string"
相关文章:
【斑马打印机】web前端页面通过BrowserPrint API连接斑马打印机进行RFID条形码贴纸打印
web前端页面通过BrowserPrint API连接斑马打印机进行RFID条形码贴纸打印 在现代物流、仓储和零售行业中,RFID和二维码技术发挥着至关重要的作用。这些技术不仅提高了效率,还增强了追踪和管理的能力。本文将介绍如何使用JavaScript和斑马打印机的BrowserPrint API来打印RFID二…...

DigitalOcean 应用托管更新:应用端到端运行时性能大幅改进
DigitalOcean 希望可以为企业提供所需的工具和基础设施,以帮助企业客户加速云端的开发,实现业务的指数级增长。为此 DigitalOcean 在 2020 年就推出了App Platform。 App Platform(应用托管) 是一个完全托管的 PaaS 解决方案&…...
c/c++对于char*的理解(联合string容器)
在C和C中,char*是一个指向字符(char)的指针。它经常被用来处理C风格的字符串,这种字符串是以空字符(\0)结尾的字符数组。以下是关于char*的一些关键点: C风格的字符串: C风格的字符…...

Web前端三大主流框架是什么?
Web前端开发领域的三大主流框架分别是Angular、React和Vue.js。它们在Web开发领域中占据着重要的地位,各自拥有独特的特点和优势。 Angular Angular是一个由Google开发的前端框架,最初版本称为AngularJS,后来升级为Angular。它是一个完整的…...

一个基于servlet的MVC项目-登录验证
一、MVC的概念 MVC是Model、View、Controller的缩写,分别代表 Web 应用程序中的3种职责1 模型:用于存储数据以及处理用户请求的业务逻辑。 2视图:向控制器提交数据,显示模型中的数据。 3控制器:根据视图提出的请求,判断将请求和数据交给哪个…...

Windows 11 下 kafka 的安装踩坑
安装 windows系统kafka小白入门篇——下载安装,环境配置,入门代码书写(推荐) kafka在windows下安装和使用入门教程 问题1 参考链接 运行kafka集成的zookeeper时,命令:bin\windows\zookeeper-server-star…...
二维数组:行列互换/求最大值及其所在位置/求各行各列的和/矩阵乘积/深入理解二维数组
二维数组 1.定义 只有行号可以省略,初始化 全部初始化/部分初始化/不初始化 2.元素引用 3.存储形式 :顺序存储 按行存储 4.深入理解二维数组 #include<stdio.h> #include<stdlib.h>#define M 2 #define N 3int mian() {int a[M][N] {{1,2,3},{4,5,6}}…...
The Onion Router-洋葱
目录 Tor的运作原理 Tor挑战和局限性 Tor,即The Onion Router(洋葱路由器),是一个用于匿名通信的开放网络,它旨在增强用户的隐私和安全。Tor的名字源自其设计原理,类似于将信息包装在多层“洋葱”中&…...

自动化工具 Ansible:playbooks 剧本编写
目录 前言 一、playbooks 剧本概述 1、playbooks 剧本概念 2、playbooks 剧本组成部分 3、playbooks 剧本特点与优势 二、ansible-playbook 命令 三、playbooks 剧本简单实例 1、编写 apache 的 yum 安装部署脚本 2、编写 nginx 的 yum 安装部署剧本 四、playbooks 定…...

AttributeError: module ‘flask.app‘ has no attribute ‘route‘
秒解方法一: # 未引入Flask app Flask(__name__)秒解方法二: AttributeError: ‘module’ object has no attribute ‘route’错误描述: 这个错误通常发生在使用 app.route 装饰器时,表示 Flask 无法找到 route 属性。 解决方法…...

在云计算与人工智能中,7ECloud扮演着什么样的角色
数据驱动的时代,云计算和人工智能已成为推动现代科技进步的两大引擎。作为一家专注于云计算的公司,7ECloud正是在这个领域发挥自己的力量,力图为企业提供一站式解决方案,并拥有来自厂家的源头支持,用极其低的价格助力企…...

视频推拉流EasyDSS视频直播点播平台如何优先展示正在直播的直播间?
视频推拉流EasyDSS视频直播点播平台集视频直播、点播、转码、管理、录像、检索、时移回看等功能于一体,可提供音视频采集、视频推拉流、播放H.265编码视频、存储、分发等视频能力服务,在应用场景上,平台可以运用在互联网教育、在线课堂、游戏…...

JavaEE之线程(4)——线程安全、线程安全的原因,synchronized关键字
前言 在本栏的前面的内容中,我们介绍了线程的创建、Thread 类及常见方法、线程的状态,今天我们来介绍一下关于线程的另一个重点知识——线程安全。 一、线程安全 基本概念: 线程安全的确切定义是复杂的,但我们可以这样认为&…...
Python3 笔记:分支结构
Python 中选择结构:单分支选择结构、双分支选择结构、多分支选择结构。 1、if 语句是单分支选择结构,其语法形式如下: if 条件表达式: 语句块 如果条件表达式的值为真,即条件成立,语句块将被执行;否…...

《TAM》论文笔记(上)
原文链接 [2005.06803] TAM: Temporal Adaptive Module for Video Recognition (arxiv.org) 原文代码 GitHub - liu-zhy/temporal-adaptive-module: TAM: Temporal Adaptive Module for Video Recognition 原文笔记 What: TAM: Temporal Adaptive Module for …...

【Java的抽象类和接口】
1. 抽象类 1.1 抽象类概念 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果 一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。 以上代码中…...

今天开发了一款软件,我竟然只用敲了一个字母(文末揭晓)
软件课题:Python实现打印100内数学试题软件及开发过程 一、需求管理: 1.实现语言:Python 2.打印纸张:A4 3.铺满整张纸 4.打包成exe 先看效果: 1. 2.电脑打印预览 3.打印到A4纸效果(晚上拍的&#x…...

【C++杂货铺】红黑树
目录 🌈前言🌈 📁 红黑树的概念 📁 红黑树的性质 📁 红黑树节点的定义 📁 红黑树的插入操作 📁 红黑树和AVL树的比较 📁 全代码展示 📁 总结 🌈前言…...

css--控制滚动条的显示位置
各种学习后的知识点整理归纳,非原创! ① direction属性 滚动条在左侧显示② transform:scaleY() 滚动条在上侧显示 正常的滚动条会在内容超出规定的范围后在区域右侧和下侧显示在有些不正常的需求下会希望滚动条在上侧和左侧显示自己没有想到好的解决方案…...

华为设备display查看命令
display version //查看版本信息 display current-configuration //查看配置详情 display this //查看当前视图有效配置 display ip routing-table //查看路由表 display ip routing-table 192.168.3.1 //查看去往3.1的路由 display ip interface brief //查看接口下ip信息 dis…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
Bean 作用域有哪些?如何答出技术深度?
导语: Spring 面试绕不开 Bean 的作用域问题,这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开,结合典型面试题及实战场景,帮你厘清重点,打破模板式回答,…...

aardio 自动识别验证码输入
技术尝试 上周在发学习日志时有网友提议“在网页上识别验证码”,于是尝试整合图像识别与网页自动化技术,完成了这套模拟登录流程。核心思路是:截图验证码→OCR识别→自动填充表单→提交并验证结果。 代码在这里 import soImage; import we…...