基于Native.js 实现的连接蓝牙打印机
打印效果图核心代码测试代码运行设备及环境PS:PPS:Demo
打印效果图
核心代码
export const Bluetooth = function () {
let main
= null,
BluetoothAdapter
= null,
UUID = null,
uuid
= null,
BAdapter
= null,
device
= null,
bluetoothSocket
= null,
outputStream
= null,
OutputStreamWriter
= null,
writer
= null
this.status
= 0
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
= 1
this.queryBindDevice()
}
this.queryBindDevice = function () {
var lists
= BAdapter
.getBondedDevices()
plus
.android
.importClass(lists
)
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
= 0
return
}
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
)
}
this.closeConnect = function () {
bluetoothSocket
.close()
outputStream
.close()
OutputStreamWriter
.close()
bluetoothSocket
= null
outputStream
= null
OutputStreamWriter
= null
device
= null
this.status
= 0
}
this.feedPoint = function (n
) {
const point
= n
|| 8
writer
.write(0x1B)
writer
.write(0x4A)
writer
.write(point
)
writer
.flush()
}
this.feedLine = function (n
) {
const line
= n
|| 1
writer
.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()
}
this.printLine = function (lineNum
) {
for (let i
= 0; i
< lineNum
; i
++) {
writer
.write('\n')
}
writer
.flush()
}
this.setPrintPosition = function (n
) {
let m
= n
|| 1
writer
.write(0x1B)
writer
.write(0x61)
writer
.write(m
)
writer
.flush()
}
this.setPrintLocation = function (light
, weight
) {
writer
.write(0x1B)
writer
.write(0x24)
writer
.write(light
)
writer
.write(weight
)
writer
.flush()
}
this.printTabSpace = function (n
) {
for (let i
= 0; i
< n
; i
++) {
writer
.write('\t')
}
writer
.flush()
}
this.setPrintRotate = function (n
) {
writer
.write(0x1B)
writer
.write(0x56)
writer
.write(n
)
writer
.flush()
}
this.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 ')
}
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 ')
}
this.printQrcode = function (byteStr
) {
if (!main
) {
mui
.toast('设备未进行配对!')
return
}
var moduleSize
= 8
var bytes
= plus
.android
.invoke(byteStr
, 'getBytes', 'gbk')
var length
= bytes
.length
console
.log(length
)
writer
.write(0x1D)
writer
.write('(k')
writer
.write(length
+ 3)
writer
.write(0)
writer
.write(49)
writer
.write(80)
writer
.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)
writer
.write(0)
writer
.write(49)
writer
.write(81)
writer
.write(48)
writer
.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
.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中进行管理,在需要的组件注入实例。代码如下:
const printer
= {
namespaced
: true,
state
: {
bluetoothPrinter
: null
},
mutations
: {
setBluetoothPrinter (state
, payload
) {
state
.bluetoothPrinter
= payload
}
}
}
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!')
},
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
) return
this.submitStatus
= true
this.$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
= 0
this.recordsList
= []
this.printData
= []
await this._onLoad()
this.refresh
= false
},
async _onLoad () {
this.pagination
.page
++
await this._waitInsScrapSteel()
this.loading
= false
return 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
} = this
this.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
} = this
const len
= printData
.length
for (let i
= 0; i
< len
; i
++) {
this._print(printData
[i
])
}
},
_dataBack (msg
) {
switch (msg
) {
case '添加':
this._add()
break
case '提交':
this._submitById()
break
case '标签打印':
this._printLabel()
break
}
}
}
}
Demo
github地址:H5-bluetooth