class BluetoothTools { constructor() { this.commands = { init: [0x1b, 0x40], // 清理buffer数据,重置模式;ASC2: ESC @ print: [0x0a], //开始打印; printL5: [0x1b, 0x64, 0x05], printL6: [0x1b, 0x64, 0x06], printL8: [0x1b, 0x64, 0x08], printL10: [0x1b, 0x64, 0x10], } this.decimalData = []; //获取buffer之前的二进制数据集合; this.deviceId = null; this.initStatus = 0; //蓝牙初始化结果;0:初始化中,1-成功;2-失败; this.linked = false; //蓝牙是否为连接状态; this.timer = null; this.writeTime = 0; this.byteLength = this.isAndroid() ? 200 : 500; this.connectChangeHandler = null; } /** * 低功耗蓝牙API */ // 根据deviceId 设置传输字节最大值; setMTU(deviceId) { return new Promise((resolve, reject) => { uni.setBLEMTU({ deviceId: deviceId, mtu: 512, success: (res) => { console.log('设置MTu成功', res); resolve(res) }, fail: (err) => { console.log('设置mtu失败', err); this.toaset('设置mtu失败!') reject(err) } }) }) } // 根据deviceId/mac地址 查询serviceId列表; getServiceId(deviceId) { return new Promise((resolve, reject) => { uni.getBLEDeviceServices({ deviceId: deviceId, success: res => { resolve(res) }, fail: err => { console.log('获取serviceId失败', err); reject(err) } }) }) } // 根据deviceId 和 serviceId 获取特征Id; getCharId(deviceId, serviceId) { return new Promise((resolve, reject) => { uni.getBLEDeviceCharacteristics({ deviceId: deviceId, serviceId: serviceId, success: res => { resolve(res) }, fail: err => { console.log('获取特征id失败', err); reject(err) } }) }) } // 写入数据; writeBLE(deviceId, serviceId, charId, buffer) { // console.log(deviceId, serviceId, charId, buffer.byteLength); // return; let _this = this; return new Promise((resolve, reject) => { uni.writeBLECharacteristicValue({ deviceId: deviceId, //设备Id、mac地址; serviceId: serviceId, //服务id; characteristicId: charId, //特征id; value: buffer, //指令buffer数据; writeType: 'write', //'writeNoResponse', success: res => { // console.log('数据写入成功', res); _this.writeTime = 0; resolve(res) }, fail: err => { console.log('写入失败:', Date.now()); reject(err); } }) }) } /** * 具体功能实现 */ // 打印传入的位图信息 async printImage(res) { if (!this.deviceId) { this.toast('未检测到蓝牙设备id'); this.hideLoading() return; } this.isAndroid() && await this.setMTU(this.deviceId); const imgArr = this.getImgArray(res); // return; const { serviceId, charId } = await this.getWriteIds(this.deviceId); this.startPrint(this.deviceId, serviceId, charId, imgArr); } // 开始打印; async startPrint(deviceId, serviceId, charId, cmd) { // 初始化; let initArr = Array.from(this.commands.init).concat(Array.from(this.commands.print)); let initBuffer = new Uint8Array(initArr).buffer; await this.writeMidWare(deviceId, serviceId, charId, initBuffer) // let cmds = Array.from(this.commands.init).concat(Array.from(cmd)).concat(Array.from(this.commands.printL10)); // 分别传输指令; let cmds = Array.from(cmd); console.log(cmds.length); if (cmds.length > this.byteLength) { let cmdArrs = []; let newCmds = Array.from(cmds); let length = Math.ceil(cmds.length / this.byteLength); for (let i = 0; i < length; i++) { cmdArrs.push(newCmds.slice(this.byteLength * i, this.byteLength * (i + 1))); } for (let i = 0; i < cmdArrs.length; i++) { console.log(i, cmdArrs.length); let buffer = new Uint8Array(cmdArrs[i]).buffer; await this.writeMidWare(deviceId, serviceId, charId, buffer) } } else { let buffer = new Uint8Array(cmds).buffer; cmds.length && await this.writeMidWare(deviceId, serviceId, charId, buffer) } // 打印空行; let printLCmd = Array.from(this.commands.printL5); let printLBuffer = new Uint8Array(printLCmd).buffer; await this.writeMidWare(deviceId, serviceId, charId, printLBuffer); } // 处理安卓写入失败的问题; writeMidWare(deviceId, serviceId, charId, buffer) { let _this = this; return new Promise((resolve, reject) => { this.writeBLE(deviceId, serviceId, charId, buffer).then(res => { resolve(res) }).catch(err => { // console.log(111111, _this.writeTime); if (_this.writeTime < 50) { _this.writeTime++; return new Promise((reso, reje) => { clearTimeout(this.timer) this.timer = setTimeout(() => { reso(this.writeMidWare(deviceId, serviceId, charId, buffer)) }, 100) }) } else { _this.writeTime = 0; _this.hideLoading(); _this.toast('数据写入失败,请走纸后重试!'); reject(err); } }).then(res => { resolve(res) }) }) } // 位图信息转换为打印指令; getImgArray(res) { var w = res.width; var width = parseInt((res.width + 7) / 8 * 8 / 8); var height = res.height; let data = [29, 118, 48, 0]; // let data = [0x1d, 0x76, 0x30, 0]; data.push(parseInt(width % 256)); data.push(parseInt(width / 256)); data.push(parseInt(res.height % 256)); data.push(parseInt(res.height / 256)); var bits = new Uint8Array(height * width); for (let y = 0; y < height; y++) { for (let x = 0; x < w; x++) { var color = res.data[(y * w + x) * 4 + 1]; if (color > 128) { bits[parseInt(y * width + x / 8)] |= (0x80 >> (x % 8)); } } } for (let i = 0; i < bits.length; i++) { data.push((~bits[i]) & 0xFF) } return data; } // 获取写入数据需要的ids; async getWriteIds(deviceId) { return new Promise(async (resolve, reject) => { let serviceIdData = await this.getServiceId(deviceId); let services = serviceIdData.services; // console.log(services); let charId, serviceId; for (let i = 0; i < services.length; i++) { const chars = await this.getCharId(deviceId, services[i].uuid); // console.log(services[i].uuid, chars); const charItem = chars.characteristics.filter(item => item.properties.write)[0]; if (charItem) { charId = charItem.uuid; serviceId = services[i].uuid; // break; // console.log(charId, serviceId); } } resolve({ charId: charId, serviceId: serviceId }) }) } isAndroid() { return uni.getSystemInfoSync().osName === 'android' } } export default BluetoothTools;