uni-app H5+ 连接蓝牙打印机打印文字及二维码

article/2025/8/26 3:27:09

基于Native.js 实现的连接蓝牙打印机

    • 打印效果图
    • 核心代码
    • 测试代码
    • 运行设备及环境
    • PS:
    • PPS:
    • Demo

打印效果图

在这里插入图片描述

核心代码

/*** @Description: 蓝牙打印类  基于h5+ Native.js* @Author: EricLee* @Date: 2020-10-14 13:53:23* @Param: mod* @Return: $*/export const Bluetooth = function () {
// 全局 变量let main = null,BluetoothAdapter = null,UUID = null,uuid = null,BAdapter = null,device = null,bluetoothSocket = null,outputStream = null,OutputStreamWriter = null,writer = nullthis.status = 0  // 和设备的连接状态: 0 未连接   1 连接中 2 已连接 (可以打印) 注: ** 此状态不是 手机蓝牙和设备的配对状态 **// 初始化this.initState = function () {main = plus.android.runtimeMainActivity()BluetoothAdapter = plus.android.importClass('android.bluetooth.BluetoothAdapter')BAdapter = BluetoothAdapter.getDefaultAdapter()UUID = plus.android.importClass('java.util.UUID')uuid = UUID.fromString('00001101-0000-1000-8000-00805F9B34FB')this.status = 1this.queryBindDevice()}// 获取配对设备 mac地址this.queryBindDevice = function () {var lists = BAdapter.getBondedDevices()plus.android.importClass(lists)// var resultDiv = document.getElementById('bluetooth_list')var iterator = lists.iterator()plus.android.importClass(iterator)console.log('==> 设备列表长度', lists.size())if (lists.size() == 0) {mui.toast('连接失败!未检测到已配对成功的设备!')return}if (lists.size() > 1) {mui.toast('连接失败!检测到多个配对成功设备!')return}while (iterator.hasNext()) {var d = iterator.next()plus.android.importClass(d)console.log(d.getAddress())console.log(d.getName())this.createConnect(d.getAddress()) // 创建连接}}// 建立连接this.createConnect = function (mac) {if (!mac) {mui.toast('连接失败!未能获取设备MAC地址!')this.status = 0return}device = BAdapter.getRemoteDevice(mac) // 连接打印机plus.android.importClass(device)// 只需建立一次连接,多次调用不能正常打印 !!!bluetoothSocket = device.createInsecureRfcommSocketToServiceRecord(uuid)plus.android.importClass(bluetoothSocket)if (!bluetoothSocket.isConnected()) {console.log('断开了,需要重新连接,连接中')bluetoothSocket.connect()}mui.toast('打印机已准备就绪,可以打印!')this.status = 2// 注册打印类outputStream = bluetoothSocket.getOutputStream()plus.android.importClass(outputStream)OutputStreamWriter = plus.android.importClass('java.io.OutputStreamWriter')writer = new OutputStreamWriter(outputStream, 'GBK')plus.android.importClass(writer)}// 关闭IO 关闭连接// 关闭页面时必需调用该方法,要不下次不能正常连接设备 !!!this.closeConnect = function () {bluetoothSocket.close()outputStream.close()OutputStreamWriter.close()bluetoothSocket = nulloutputStream = nullOutputStreamWriter = nulldevice = nullthis.status = 0}// 走纸 n = 点行数this.feedPoint = function (n) {const point = n || 8writer.write(0x1B)writer.write(0x4A)writer.write(point) // 点行 8 点 = 1mmwriter.flush()}// 走纸 n = 行数this.feedLine = function (n) {const line = n || 1writer.write(0x1B)writer.write(0x64)writer.write(line) // 行数writer.flush()}//  设置左边距this.setLeftMargin = function (n, m) {writer.write(0x1D)writer.write(0x4C)writer.write(n) // 行数writer.write(m) // 行数writer.flush()}// 打印空行 linNum 行数this.printLine = function (lineNum) {for (let i = 0; i < lineNum; i++) {writer.write('\n')}writer.flush()}// 设置打印 位置 // 0 右 1 中 2 右this.setPrintPosition = function (n) {let m = n || 1writer.write(0x1B)writer.write(0x61)writer.write(m) // 0 右 1 中 2 右writer.flush()}// 设置绝对打印位置this.setPrintLocation = function (light, weight) {writer.write(0x1B)writer.write(0x24)writer.write(light)  // 0≤ light ≤ 255writer.write(weight)  // 0≤ weight ≤ 2writer.flush()}// 打印空白(一个Tab的位置,约4个汉字)this.printTabSpace = function (n) {for (let i = 0; i < n; i++) {writer.write('\t')}writer.flush()}// 设置/解除字符旋转模式// 0解除旋转模式       1设置90°顺时针旋转模式         2设置180°顺时针旋转模式        3设置270°顺时针旋转模式this.setPrintRotate = function (n) {writer.write(0x1B)writer.write(0x56)writer.write(n)writer.flush()}// 打印位图  todothis.printBitmap = function (m, data) {writer.write(0x1B)writer.write(0x2A)writer.write(m)writer.write(data)}// 字符缩放this.setCharacterScale = function (n) {// 打印倍宽高if (n == 1) {writer.write(0x1B)writer.write(0x21)writer.write(16)writer.flush()writer.write(0x1B)writer.write(0x21)writer.write(32)writer.flush()} else {writer.write(0x1B)writer.write(0x21)writer.write(0)writer.flush()}}// 打印初始化 每次打印前必须调用!!!this.initPrinter = function () {writer.write(0x1B)writer.write(0x40)writer.flush()}//  打印文字 并换行this.printTextNewLine = function (byteStr) {if (!main) {mui.toast('设备未进行配对!')return}var bytes = plus.android.invoke(byteStr, 'getBytes', 'gbk')console.log(bytes)outputStream.write(bytes)outputStream.flush()// 换行writer.write('\n')writer.flush()console.log('print ')}// 打印字符串方法 byteStr 只能是字符串this.printText = function (byteStr, l, w) {if (!main) {mui.toast('设备未进行配对!')return}var bytes = plus.android.invoke(byteStr, 'getBytes', 'gbk')console.log(bytes)outputStream.write(bytes)outputStream.flush()console.log('print ')// device = null}/*** @Description: 二维码打印* @Author: EricLee* @Date: 2020-10-15 15:16:10* @Param: byteStr {String} 要打印的内容* @Return: void*/this.printQrcode = function (byteStr) {if (!main) {mui.toast('设备未进行配对!')return}// initvar moduleSize = 8var bytes = plus.android.invoke(byteStr, 'getBytes', 'gbk')var length = bytes.lengthconsole.log(length)// 缓存二维码数据writer.write(0x1D)// initwriter.write('(k')// adjust height of barcodewriter.write(length + 3) // plwriter.write(0) // phwriter.write(49) // cnwriter.write(80) // fnwriter.write(48) //writer.write(byteStr)// 二维码纠错等级writer.write(0x1D)writer.write('(k')writer.write(3)writer.write(0)writer.write(49)writer.write(69)writer.write(48)// 设置二维码块大小writer.write(0x1D)writer.write('(k')writer.write(3)writer.write(0)writer.write(49)writer.write(67)writer.write(moduleSize)// 打印已缓存的数据二维码writer.write(0x1D)writer.write('(k')writer.write(3) // plwriter.write(0) // phwriter.write(49) // cnwriter.write(81) // fnwriter.write(48) // mwriter.flush()// 二维码打印 结束console.log('print Qrcode')}
}

测试代码

<template><div><div><Button @click="_initBluetooth">{{ statusList[status] }}</Button></div><div>
<!--      <Button @click="_printText('DC:0D:30:9B:AC:99')">打印</Button>--><Button @click="_printTest(msg)">打印</Button><br/><Button @click="_printQrcode(code)">打印二维码</Button></div><div><br/><Input v-model="line" placeholder="走纸行数" /><Button @click="feed(line)">走纸</Button></div><div><br/><Input v-model="marginNum" placeholder="定位" /><Button @click="_setPrintPosition(marginNum)">定位</Button></div><div><br/><Button @click="_setCharacterScale(1)">放大</Button><Button @click="_setCharacterScale(0)">缩小</Button></div><div><br/><Input v-model="light" placeholder="light" /><Input v-model="weight" placeholder="weight" /><Button @click="_setPrintLocation(light,weight)">绝对位置</Button></div><div><br/><Input v-model="rotateNum" placeholder="旋转" /><Button @click="_setPrintRotate(rotateNum)">旋转</Button></div><div><br/><Button @click="_closeConnect()">关闭连接</Button></div></div>
</template><script>import {Bluetooth} from '../lib/bluetooth'export default {name: 'printTest',data () {return {msg: '样品内容\n' + '101013Q73898\n' + '2020-10-10 09:33:33\n' + '张三三\n',code: '191013Q7398',mac: '',line: 8,light: 0,weight: 0,rotateNum: 0,marginNum: 1,initFlag: false,bluetoothPrinter: null,text: '配对',status: 0,statusList: ['待连接','连接中','已连接']}},mounted () {this._initBluetooth()},destroyed () {this._closeConnect()},watch: {status () {console.log('status==>', this.status)if (this.status == 2) {this._loading(false)}}},methods: {_loading (flag) {if (flag) {this.$vux.loading.show({text: 'Loading'})setTimeout(() => {this.$vux.loading.hide()}, 5000)} else {this.$vux.loading.hide()}},// 初始化并配对设备_initBluetooth () {if (!this.bluetoothPrinter) {this.bluetoothPrinter = new Bluetooth()this._loading(true)console.log(this.bluetoothPrinter.status)}this.bluetoothPrinter.initState()this.status = this.bluetoothPrinter.status},_printTest (msg) {this.bluetoothPrinter.initPrinter()this.bluetoothPrinter.setPrintPosition(1) // 居中 打印this.bluetoothPrinter.printQrcode(msg)this.bluetoothPrinter.feedPoint(20)this.bluetoothPrinter.printTextNewLine('样品111')this.bluetoothPrinter.printTextNewLine('101013Q73898')this.bluetoothPrinter.printTextNewLine('2020-10-10 09:33:33')this.bluetoothPrinter.printTextNewLine('张三三')this.bluetoothPrinter.printLine(3)},_printQrcode (msg) {this.bluetoothPrinter.initPrinter()this.bluetoothPrinter.printTabSpace(10)// this.bluetoothPrinter.setPrintPosition(2)this.bluetoothPrinter.printQrcode(msg)},feed (n) {this.bluetoothPrinter.feedPoint(n)},_closeConnect () {if (this.bluetoothPrinter) {this.bluetoothPrinter.closeConnect()}},_setPrintLocation (l, w) {this.bluetoothPrinter.setPrintLocation(l, w)},_setPrintRotate (l) {this.bluetoothPrinter.setPrintRotate(l)},_setCharacterScale (l) {this.bluetoothPrinter.setCharacterScale(l)},_setPrintPosition (l) {this.bluetoothPrinter.setPrintPosition(l)}}}
</script><style scoped></style>

运行设备及环境

IDE:Hbuilder X 2.8.13
测试机型:红米 note4 android6.0
测试打印机:科密PB8001
打印指令类型:ESC/POS ESC/POS指令参考文档

PS:

本文未提供连接蓝牙设备的方法,如有需要请点传送门 —» H5+连接蓝牙打印机

PPS:

只初始化一次即可持续打印实现
可以把 new Bluetooth() 的实例的初始化放到store中进行管理,在需要的组件注入实例。代码如下:


// store
const printer = {namespaced: true,state: {bluetoothPrinter: null},mutations: {setBluetoothPrinter (state, payload) {state.bluetoothPrinter = payload}}
}// component
export default {data () {return {pagination: {page: 0,rows: 15},bottomList: [{name: '添加', color: '#0D55A7'},{name: '提交', color: '#11C827'},{name: '标签打印', color: '#F7AC0C'}],records: [],recordsList: [],printData: [],refresh: false, // 上拉刷新loading: false, // 下拉加载finished: false, // 是否获取到了所有数据submitStatus: false,status: 0}},computed: {...mapState('printer', {bluetoothPrinter: 'bluetoothPrinter'})},watch: {status () {console.log('status==>', this.status)if (this.status == 2) {this._loading(false)}}},mounted () {this._initBluetooth()},destroyed () {console.log('destroyed!')// this._closeConnect()},methods: {_add () {this.$store.commit('steel/removeInsSteelItem')this.$jump('typeA-insScrapSteelContractEdit', {sampleCode: '添加/编辑基本信息'})},// 全选_allCheck () {if (this.records.length === this.recordsList.length) {this.records = []return}this.records = this.recordsList.map(item => item.id)},// 提交async _submitById () {if (!this.records.length) {this.$toast('至少选择一个')return}if (this.submitStatus) returnthis.submitStatus = truethis.$vux.loading.show({text: '正在提交中...'})const result = await waitInsScrapSteelSubmit(this.records)if (result) {this._resultChange('提交成功!')this.$vux.loading.hide()} else {this._resultChange('网络问题,请重新提交!')this.$vux.loading.hide()}},_resultChange (msg) {this.$toast(msg)this._onRefresh()},// 上拉刷新async _onRefresh () {this.pagination.page = 0this.recordsList = []this.printData = []await this._onLoad()this.refresh = false},// 下拉加载async _onLoad () {this.pagination.page++await this._waitInsScrapSteel()this.loading = falsereturn true},_loading (flag) {if (flag) {this.$vux.loading.show({text: '设备配对中'})setTimeout(() => {this.$vux.loading.hide()}, 5000)} else {this.$vux.loading.hide()}},// 初始化并配对设备_initBluetooth () {if (!this.bluetoothPrinter) {const obj = new Bluetooth()this._loading(true)this.$store.commit('printer/setBluetoothPrinter', obj)console.log(this.bluetoothPrinter.status)this.bluetoothPrinter.initState()this.status = this.bluetoothPrinter.status}},_closeConnect () {if (this.bluetoothPrinter) {this.bluetoothPrinter.closeConnect()}},// 待打印数据_selectData () {if (!this.records.length) {this.$toast('至少选择一个')return false} else {const {records, recordsList} = thisthis.printData = []let data = []for (let i = 0; i < records.length; i++) {for (let j = 0; j < recordsList.length; j++) {if (records[i] === recordsList[j].id) {data.push(recordsList[j])}}}this.printData = [...data]}},// 打印方法_print (data) {this.bluetoothPrinter.initPrinter()this.bluetoothPrinter.setPrintPosition(1) // 居中 打印this.bluetoothPrinter.printQrcode(data.sampleCode) // 二维码 样品编号this.bluetoothPrinter.feedPoint(20)this.bluetoothPrinter.printTextNewLine(data.name) // 物料名称this.bluetoothPrinter.printTextNewLine(data.sampleCode) // 二维码 样品编号this.bluetoothPrinter.printTextNewLine(this.$getTime(data.obtainSampleTime, true)) // 取样时间this.bluetoothPrinter.printTextNewLine(data.obtainSampler) // 取样人this.bluetoothPrinter.feedLine(4)},// 打印标签_printLabel () {this._selectData()const {printData} = thisconst len = printData.lengthfor (let i = 0; i < len; i++) {this._print(printData[i])}},_dataBack (msg) {switch (msg) {case '添加':this._add()breakcase '提交':this._submitById()breakcase '标签打印':this._printLabel()break}}}
}

Demo

github地址:H5-bluetooth


http://chatgpt.dhexx.cn/article/MTdhmXNO.shtml

相关文章

5,uniapp功能之—打印机,打印文本和二维码等,(佳博的打印机)

效果图&#xff1a; 思路&#xff1a;1&#xff0c;一个打印按钮&#xff0c;2点击按钮弹窗一个蓝牙模块&#xff0c;选择蓝牙进行连接&#xff0c;连接成功就直接进行打印了&#xff0c;3&#xff0c;打印的内容自己设置 项目结构&#xff1a; 上代码&#xff0c;打印机参数…

批量生成二维码、打印

推荐使用GoodMES云标签打印&#xff0c;地址为&#xff1a;https://t.goodmes.com/home 1、登陆后点击设计与打印——>数据表 2、需要下载云标签打印 3、下载后进行登陆 4、登陆后无需管它&#xff0c;放在那运行即可 5、这个时候你的云标签助手就会现在在线状态 6、点…

electron打印条形码、二维码

功能&#xff1a;在electron打印条形码或者二维码 在百度搜索找不到合适的博客与插件&#xff0c;就在github上找到一个插件 electron-pos-printer 可以一键打印图片、文本、二维码、条形码、表格 不用安装其他多余插件&#xff0c;亲测十分好用 1、安装 npm install ele…

佳博打印机打印条码和二维码的方法

最近项目需求连接蓝牙打印机打印小票 其中小票中有条码和二维码&#xff0c;很多朋友刚接触打印接的打印逻辑&#xff0c;看不太明白&#xff0c;因此我之前给各位提供现成的打印方法&#xff1a; 关键就是安装打印的文档 提前写好各种打印的调用发放&#xff0c;直接在打印模…

【C#】简单二维码制作和打印

系列文章 【C#】条码管理操作手册 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/126589496 【C#】IIS平台下&#xff0c;WebAPI发布及异常处理 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/126539836 【C#】简单二维…

一维码二维码的生成及打印

VUE条形码及二维码的生成及输出到打印机 文章目录 VUE条形码及二维码的生成及输出到打印机1. 条形码的生成2. 二维码的生成3. 输出打印4. 将代码提取一下 1. 条形码的生成 安装插件 npm install jsbarcode --save github地址&#xff1a; https://github.com/lindell/JsBarcode…

C#二维码的生成及打印

窗体设计显示图 一&#xff0c;生成二维码 /// <summary>/// 生成二维码/// </summary>/// <param name"text">内容</param>/// <param name"width">宽度</param>/// <param name"height">高度</p…

生成二维码,并且打印

生成二维码&#xff0c;并且打印出来 加入依赖 //二维码依赖 npm install --save qrcodejs2 //打印依赖 npm install vue-print-nb --save在mian文件夹中使用引入并使用&#xff0c;或者按需引入 //打印依赖 import Print from vue-print-nb Vue.use(Print)本次二维码是按需引…

二维码打印

1. 二维码简介 二维码&#xff08;2-dimensional bar code&#xff09;&#xff0c;又称二维条码&#xff0c;它是用特定的几何图形按一定规律在平面&#xff08;二维方向&#xff09;上分布的黑白相间的图形&#xff0c;是所有信息数据的一把钥匙。在现代商业活动中&…

vue生成条形码和二维码并打印

文章目录 前言一、生成条形码二、生成二维码三、效果图四、打印 前言 最近有一个需求&#xff0c;需要将产品信息生成标签&#xff0c;每个信息生成一个条形码&#xff0c;拿到所有数据生成二维码&#xff0c;最后打印标签。 一、生成条形码 使用jsbarcode&#xff0c;直接in…

vue二维码生成、打印及识别

生成二维码 引入QRCode模块 npm install --save qrcode import QRCode from qrcode; 页面代码 批量创建二维码及打印&#xff0c;所以加了个v-for <div id"printDiv"/**后面打印用到的区域id*/ :disabled"hussar_20Disabled" ref"hussar_20Ref&quo…

如何将内网ip映射到外网

这个百度经验上就有&#xff0c;不过对于着急使用的我来说&#xff0c;差了最后一步。所以还是一起记上吧。 第一步 首先登陆你的路由器&#xff0c;就改密码那个。一般就用浏览器直接打开192.168.1.1就可以&#xff0c;账号密码有可能是 admin admin吧&#xff0c;默认可能是…

VMWare虚拟机局域网网络配置,主机访问虚拟机上的网站(端口映射)

文章目录 1 problem2 背景知识3 配置主机网络4 配置虚拟机网络 1 problem 如题&#xff0c;现在虚拟机的80端口和8080端口都有一个网站&#xff0c;我们想要在主机访问它。 2 背景知识 VmWare支持3种网络连接模式。 1、桥接模式&#xff1a; 所谓桥接就是把两个本来分开…

映射公网的几种方式

转载自&#xff1a;http://blog.csdn.net/sadshen/article/details/48240519 这篇文章花了好几天&#xff0c;系统地梳理出了映射公网的几种方式。虽然是针对微信开发的外网服务器来寻找解决方案&#xff0c;但这个知识梳理可能会在其他地方也受益。平常我也有用TeamViewer&…

VMware NAT端口映射 外网可以访问内网虚拟机

我想尝试的是利用本机的ipport来访问虚拟机上的web服务器&#xff0c;因为这样的话&#xff0c;我就能够将我的web服务器部署成为一个能让外网访问的服务器了&#xff0c;首先说下我的环境&#xff1a; 主机&#xff1a;系统win7&#xff0c;ip地址172.18.186.210 虚拟机版本是…

如何把内网IP映射到公网IP

鸽子出品 2017-12-05 22:28:22 我们讲了如何搭建网站&#xff0c;可是有很多小伙伴私信跟我说怎么映射&#xff0c;今天我就教大家如何把内网地址映射到公网&#xff01; 我们所需要的工具有&#xff1a; 内网IP&#xff08;这个是品&#xff0c;也是必有的&#xff01;&…

简单内网映射到公网方法--免费

我是一名Android API Player&#xff0c;最近公司需要做微信公众号二次开发&#xff0c;我跟着学学&#xff0c;公司后台.net。 我mac安装windows之后用vs感觉太差了&#xff0c;可能是我的mac要淘汰了吧。 所以我决定用java后台来跟着做。 仔细一想我没有服务器啊。 再仔细…

本地主机搭建服务器后如何让外网访问?快解析内网端口映射

本地主机搭建应用、部署服务器后&#xff0c;在局域网内是可以直接通过计算机内网IP网络地址进行连接访问的&#xff0c;但在外网电脑和设备如何访问呢&#xff1f;由于内网环境下&#xff0c;无法提供公网IP使用&#xff0c;外网访问内网就需要一个内外网转换的介质。这里介绍…

内网和外网之间的通信(端口映射原理)

内网和外网之间的通信&#xff08;端口映射原理&#xff09; 首先解释一下“内网”与“外网”的概念&#xff1a; 内网&#xff1a;即所说的局域网&#xff0c;比如学校的局域网&#xff0c;局域网内每台计算机的IP地址在本局域网内具有互异性&#xff0c;是不可重复的。但两…

实现内网通过外网域名访问NAT映射的内网服务器

大家都知道在用Huawei的中低端路由器做NAT地址映射时只能支持 “外网访问” 不支持 “内网访问”。也就是说只支持NAT映射后外网IP通过外网域名&#xff08;外网IP&#xff09;访问NAT映射的服务器 &#xff0c;不支持NAT映射后内网IP通过外网域名&#xff08;外网IP&#xff0…