微信小程序连接蓝牙打印机示例
小程序连接蓝牙打印机打印文本与二维码等示例在 github 上都能找到一些,唯独打印图片这个案例几乎没有。希望能帮助到有打印图片需求的小伙伴。
- 测试打印机:凯盛诺 PTP-II-UBC 58mm 便携热敏打印机
- 测试环境有:Android微信 , IOS微信;其中 Android 和 IOS 在打印文本与二维码速率相对一致,但 IOS 打印图片几乎慢到无法打印的情况(听说蓝牙打印机在 IOS 中受限制,需要与 IOS 合作授权,在斑马品牌的一款打印机用 IOS 就能打印出来。即使是 Android ,小程序打印图片比打印文本会慢许多,并不是打印机的问题,而是小程序只能使用低功率蓝牙,受限在一次发送 20 个字节的数据,需要分段递归发送,图片数据可以达到几万、几十万个字节。)
- 打印机指令类型:ESC/POS 指令集 (打印机产家都会提供对应的指令文档,此 demo 中使用十进制的数据格式的指令,十六进制的指令或者更多指令的使用方式可以参考另一个示例小程序蓝牙打印 miniprogram-bluetoothprinter)
示例功能
- 连接蓝牙打印机
- 打印文本 (打印中文出现乱码,因为打印机默认的编码是 GB2312,需要将 UTF-8 转 GB2312,这里用的轻小的GBK 库,也可以使用text-encoding)
- 打印二维码(使用指令打印内置二维码样式,或者用图片方式打印定制二维码)
- 打印任意图片(此示例的重点, canvas 绘制图片,wx.canvasGetImageData()取得 Uint8ClampedArray后再转成位图数据,使用
图片水平取模数据打印
指令打印位图数据)
效果图




Demo 中连接打印机的流程
- 初始化蓝牙模块 wx.openBluetoothAdapter()
- 初始化完成后搜寻附近的蓝牙设备 wx.startBluetoothDevicesDiscovery()
- 监听寻找到新设备的事件 wx.onBluetoothDeviceFound()
- 在监听寻找到新设备的事件回调中获取所有蓝牙设备列表 wx.getBluetoothDevices()
- 连接低功耗蓝牙设备 wx.createBLEConnection()
- 连接成功后获取蓝牙设备服务 wx.getBLEDeviceServices()
- 在服务中取(notify=true || indicate=true) && write=true 的特征值的 uuid: wx.getBLEDeviceCharacteristics()
- 完成后停止搜寻 wx.stopBluetoothDevicesDiscovery()
- 向低功耗蓝牙设备特征值中写入二进制数据 wx.writeBLECharacteristicValue()
- 离开页面时取消蓝牙连接 wx.closeBLEConnection()
- 关闭蓝牙模块 wx.closeBluetoothAdapter()
关于找蓝牙设备中能用的 Characteristic,这里贴出对应的代码,关注注释部分
/**
* 以Promise方式调用 微信api
* @param {string} name 微信api的名称 ,如 wxAsyncPromise("getSystemInfo",options)
* @param {object} options 除了success 和 fail 的其他参数
* @returns
*/
export function wxAsyncPromise(name, options) {
return new Promise((resolve, reject) => {
wx[name]({
...(options || {
}),
success: function (res) {
resolve(res);
},
fail: function (res) {
reject(res);
},
});
});
}
//在多个服务services中递归查找能用的特征值
//deviceId : 已连接的蓝牙设备id
//services : wx.getBLEDeviceServices()取得的服务
export function getDeviceCharacteristics(deviceId, services = [], success, fail) {
services = services.slice(0);
if (services.length) {
const serviceId = services.shift().uuid;
wxAsyncPromise('getBLEDeviceCharacteristics', {
deviceId,
serviceId,
})
.then((res) => {
console.log('getBLEDeviceCharacteristics', deviceId, serviceId, res);
let finished = false;
let write = false;
let notify = false;
let indicate = false;
//有斑马品牌的一款打印机中res.characteristics的所有uuid都是相同的,
//找所有的properties存在(notify || indicate) && write(如果只写入数据只要write=true也可以)这种情况就说明这个uuid是可用的
//(不确保所有的打印机都能用这种方式取得uuid,
//在凯盛诺打印机的res.characteristic只有一个uuid,所以也能用这个方式)
for (var i = 0; i < res.characteristics.length; i++) {
if (!notify) {
notify = res.characteristics[i].properties.notify;
}
if (!indicate) {
indicate = res.characteristics[i].properties.indicate;
}
if (!write) {
write = res.characteristics[i].properties.write;
}
if ((notify || indicate) && write) {
/* 获取蓝牙特征值uuid */
success &&
success({
serviceId,
characteristicId: res.characteristics[i].uuid,
});
finished = true;
break;
}
}
if (!finished) {
getDeviceCharacteristics(deviceId, services, success, fail);
}
})
.catch