小程序连接蓝牙打印机实现打印功能
- 这真是一块超级难啃的骨头,我也是参考了很多文章才勉强理解,但是如果你啃动了,那你以后也有了拿得出手的资本了
完整DEMO地址esc打印模式可直接下载下来使用
- uniApp的cpcl打印模式DEMD地址 兼容性更好速度打印速度更快支持的文本模式更好,微信小程序与uniapp通用,可直接使用
- 搜索与连接蓝牙,这个我就不过多讲解了
btn(){
this.setData({
list:[]
})
var that=this
wx.startBluetoothDevicesDiscovery({
success(res){
//监听新设备
wx.onBluetoothDeviceFound(function(res) {
var devices = res.devices;
if(devices[0].name!=''){
// this.list.push(devices[0])
var list=that.data.list
list.push(devices[0])
that.setData({
list,
})
}
// console.log('new device list has founded')
// console.log(ab2hex(devices[0].advertisData))
})
},
fail(res){
console.log('搜索蓝牙失败',res)
}
})
},
//连接蓝牙
connect(v){
wx.showLoading({
mask:true,
title:'连接蓝牙中'
})
var that=this
let {text} = v.currentTarget.dataset
this.setData({
id:text.deviceId
})
wx.createBLEConnection({
deviceId:text.deviceId,
timeout:9000,
success(rse){
console.log('连接蓝牙情况',rse)
wx.getBLEDeviceServices({
deviceId:text.deviceId,
complete(rse){
if(rse.errCode!=0){
if(rse.errCode==10012){
wx.showToast({
title: '连接蓝牙超时请重试',
icon: 'error',
duration: 1000
})
}else{
wx.showToast({
title: '连接蓝牙异常',
icon: 'error',
duration: 1000
})
}
return
}
//查询特征值
that.setData({
inactive:[]
})
for(var i in rse.services){
wx.getBLEDeviceCharacteristics({
deviceId:text.deviceId,
serviceId:rse.services[i].uuid,
complete(rse){
if(that.data.inactive[0]){
return
}
for(var j in rse.characteristics){
if(rse.characteristics[j].properties.write){
var arr=that.data.inactive
console.log(that.data.inactive,'查询值')
arr.push({
deviceId:rse.deviceId,
serviceId:rse.serviceId,
characteristicId:rse.characteristics[j].uuid,
name:text.name
})
wx.setStorageSync('bluetooth', v)
that.setData({
inactive:arr
})
wx.showToast({
title: '连接成功',
duration: 1000
})
that.data.status==1?that.print():that.data.status==2?that.receipt():''
// that.speedUp(rse.deviceId)
break
}
}
if(!that.data.inactive[0]){
wx.showToast({
title: '获取蓝牙服务失败',
icon: 'error',
duration: 1000
})
}
}
})
}
}
})
},
fail(rse){
console.log('链接失败')
},
complete(){
wx.stopBluetoothDevicesDiscovery({
success(){
console.log('停止搜索蓝牙')
}
})
}
})
},
2.打印文字Github实例
writeBLECharacteristicValue(n) {
let printerJobs = new PrinterJobs();
printerJobs
.print()
.setAlign('LT')
.print(printerUtil.fillLine())
.setAlign('ct')
.print('回单联')
.setAlign('LT')
.setLineSpacing(40)
.print(data.storename?printerUtil.inline(`门店:${data.storename}`, `${this.time()}`):printerUtil.inline(`车牌号:xxxx`, `区域:xxxx`))
.print(printerUtil.inline(`快递线路:${data.shipping_name}`,`会员ID:${data.uid}`))
.print(printerUtil.inline(`寄件人:${data.jijianren}`, `电话:${data.jijianmobile}`))
// .print(printerUtil.fillAround(`时间: ${this.time()}`))
let buffer = printerJobs.buffer();
console.log('ArrayBuffer', 'length: ' + buffer.byteLength, ' hex: ' + ab2hex(buffer),buffer,'查看');
// 1.并行调用多次会存在写失败的可能性
// 2.建议每次写入不超过20字节
// 分包处理,延时调用
const maxChunk = 20;
const delay = 20;
for (let i = 0, j = 0, length = buffer.byteLength; i < length; i += maxChunk, j++) {
let subPackage = buffer.slice(i, i + maxChunk <= length ? (i + maxChunk) : length);
setTimeout(this._writeBLECharacteristicValue, j * delay, subPackage);
}
},
_writeBLECharacteristicValue(buffer) {
let {deviceId,serviceId,characteristicId}=this.data.inactive[0]
wx.writeBLECharacteristicValue({
deviceId: deviceId,
serviceId: serviceId,
characteristicId: characteristicId,
value: buffer,
success(res) {
console.log('writeBLECharacteristicValue success', res)
},
fail(res) {
console.log('writeBLECharacteristicValue fail', res)
}
})
},
3.打印二维码
根据订单号生成二维码,然后二维码可以打印出来,生成二维码的话,建议使用weapp.qrcode.js
printImgT(device, text,n) {//二维码
let tthis = this;
const ctx = wx.createCanvasContext('canvas');
ctx.clearRect(0, 0, 200, 200);
drawQrcode({
canvasId: 'canvas',
text: String(text),
width: 200,
height: 200,
callback(e) {
// wxbarcode.barcode('barcode', tthis.data.code, 680, 160,function(){
setTimeout(() => {
// 获取图片数据
wx.canvasGetImageData({
canvasId: 'canvas',
x: 0,
y: 0,
width: 200,
height: 200,
success(res) {
let arr = tthis.convert4to2(res.data);
let data = tthis.convert8to1(arr); //宽除8 //高本值
const cmds = [].concat([27, 97,1], [29, 118, 48, 0, 25, 0, 200, 0], data, [27, 74, 3], [27, 64]);
const buffer = toArrayBuffer(Buffer.from(cmds, 'gb2312'));
let arrPrint = [];
arrPrint.push(util.sendDirective([0x1B, 0x40]));
arrPrint.push(util.sendDirective([0x1B, 0x61, 0x01])); //居中
for (let i = 0; i < buffer.byteLength; i = i + 20) { //限制输入数据
arrPrint.push(buffer.slice(i, i + 20));
}
// arrPrint.push(util.sendDirective([0x1B, 0x61, 0x01])); //居中
arrPrint.push(util.hexStringToBuff(`扫码识别单号\n`));
// arrPrint.push(util.hexStringToBuff("\n"));
tthis.printInfo(device, arrPrint);
}
})
}, 1000);
// }());
}
});
},
- 在将值传输时因为每次只能传输20字节的数据,二维码打印会很慢,于是我想法将每次输入更改为异步操作提高了一些打印速度
printInfo: function(device, arr, callback) {
let tthis = this;
if (arr.length > 0) {
arr.shift();
setTimeout(tthis.sendStr, 10, arr[0]); //将同步更改为异步
tthis.printInfo(device, arr, callback);
} else {
// callback ? callback() : '';
}
},
sendStr: function(bufferstr) {
let {deviceId,serviceId,characteristicId}=this.data.inactive[0]
let tthis = this;
wx.writeBLECharacteristicValue({
deviceId: deviceId,
serviceId: serviceId,
characteristicId: characteristicId,
value: bufferstr,
success: function(res) {
console.log('发送成功', res)
},
failed: function(res) {
console.log("数据发送失败:" + JSON.stringify(res))
},
// complete: function(res) {
// console.log("发送完成:" + JSON.stringify(res))
// }
})
},
- 4合1,8合1
//4合1
convert4to2(res) {
let arr=[]
for (let i = 0; i < res.length; i++) {
if (i % 4 == 0) {
let rule = 0.29900 * res[i] + 0.58700 * res[i + 1] + 0.11400 * res[i + 2];
if (rule > 200) {
res[i] = 0;
} else {
res[i] = 1;
}
arr.push(res[i]);
}
}
return arr;
},
//8合1
convert8to1(arr) {
let data = [];
for (let k = 0; k < arr.length; k += 8) {
let temp = arr[k] * 128 + arr[k + 1] * 64 + arr[k + 2] * 32 + arr[k + 3] * 16 + arr[k + 4] * 8 + arr[k + 5] * 4 + arr[k + 6] * 2 + arr[k + 7] * 1
data.push(temp);
}
return data;
}
4.图片的打印
- 与二维码打印相似将网络图片通过wx.getImageInfo转换为能识别的进制
printImg() {
let tthis = this;
wx.getImageInfo({
src: 'http://zdht-it618jifen.oss-cn-beijing.aliyuncs.com/images/161932136004239.png',
success: function (ret) {
setTimeout(() => {
var path = ret.path;
var canvas = wx.createCanvasContext('shareCanvas')
canvas.drawImage(path, 0, 0, 280, 100);
canvas.draw()
wx.canvasGetImageData({
canvasId: 'shareCanvas',
x: 0,
y: 0,
width: 280,
height: 100,
success(res) {
let arr = tthis.convert4to1(res.data);
let data = tthis.convert8to1(arr);
const cmds = [].concat([27, 97, 1], [29, 118, 48, 0, 35, 0, 100, 0], data, [27, 74, 3], [27, 64]);
const buffer = toArrayBuffer(Buffer.from(cmds, 'gb2312'));
let arrPrint = [];
arrPrint.push(util.sendDirective([0x1B, 0x40]));
for (let i = 0; i < buffer.byteLength; i = i + 20) {
arrPrint.push(buffer.slice(i, i + 20));
}
tthis.printInfo('xfz',arrPrint,stat,'3');
},
fail: function (error) {
console.log("error:" + error);
}
})
}, 200);
},
})
},
- 打印出来效果图
- 如果不喜欢黑色背景,可将4和1 的 0 1 打印参的条件进行反转
convert4to1(res) {
let arr = [];
for (let i = 0; i < res.length; i++) {
if (i % 4 == 0) {
let rule = 0.29900 * res[i] + 0.58700 * res[i + 1] + 0.11400 * res[i + 2];
if (rule > 200) {
res[i] = 0;
} else {
res[i] = 1;
}
arr.push(res[i]);
}
}
return arr;
},
5.整体打印效果如图