一、根据需求去实现的打印小票,show him the code:uniapp-bluetooth: uniapp连接蓝牙打印!
对您有所帮助记得点亮star,谢谢!
二、整个连接蓝牙思路:
-
获取蓝牙适配器:首先,需要通过
uni.getBluetoothAdapter
方法获取蓝牙适配器对象。可以使用该对象进行后续的蓝牙操作。 -
初始化蓝牙适配器:使用
uni.openBluetoothAdapter
方法初始化蓝牙适配器。在初始化成功后,可以进行蓝牙设备的搜索和连接操作。 -
搜索蓝牙设备:使用
uni.startBluetoothDevicesDiscovery
方法开始搜索蓝牙设备。可以设置搜索的时间和过滤条件,然后通过监听onBluetoothDeviceFound
事件获取搜索到的蓝牙设备列表。 -
连接蓝牙设备:选择要连接的蓝牙设备后,使用
uni.createBLEConnection
方法连接蓝牙设备。可以通过监听onBLEConnectionStateChange
事件获取连接状态的变化。 -
获取蓝牙设备的服务和特征值:连接成功后,使用
uni.getBLEDeviceServices
方法获取蓝牙设备的服务列表。然后,使用uni.getBLEDeviceCharacteristics
方法获取每个服务的特征值列表。 -
监听蓝牙设备的特征值变化:对于需要监听特定特征值变化的操作,可以使用
uni.notifyBLECharacteristicValueChange
方法监听特征值的变化。当特征值发生变化时,会触发onBLECharacteristicValueChange
事件。 -
发送和接收数据:使用
uni.writeBLECharacteristicValue
方法向蓝牙设备发送数据。可以通过监听onBLECharacteristicValueChange
事件获取蓝牙设备返回的数据。 -
断开蓝牙连接:使用
uni.closeBLEConnection
方法断开蓝牙连接
三、代码:
<script setup>
import {
ref
} from 'vue'
import {
onLoad
} from '@dcloudio/uni-app'
import toArrayBuffer from 'to-array-buffer'
import {
Buffer
} from 'buffer/';
import * as util from '../../utils/util.js'
import drawQrcode from '../../utils/weapp.qrcode.esm.js'
const devices = ref([])
const bindDevice = ref('')
const platform = ref('')
onLoad(() => {
getSystemInfo()
})
//得到系统信息
const getSystemInfo = () => {
wx.getSystemInfo({
success(res) {
platform.value = res.platform
}
})
}
//查询蓝牙设备
const searchPrint = () => {
//避免连接过多,先断开所有连接,每次初始化才能确保稳定,想跳过的,自己在踩坑44.
wx.closeBluetoothAdapter({
complete: () => {
//初始化蓝牙
wx.openBluetoothAdapter({
success: (res) => {
startBluetoothDevicesDiscovery();
},
fail: (res) => {
if (res.errCode === 10001) {
console.log('蓝牙未开启');
} else {
console.log('蓝牙初始化失败');
}
}
})
}
});
}
//开始搜寻附近的蓝牙设备
const startBluetoothDevicesDiscovery = () => {
//停止蓝牙搜索
stopBluetoothDevicesDiscovery();
//开启蓝牙搜索
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: false,
success: (res) => {
console.log('startBluetoothDevicesDiscovery success', res)
//搜索,监听返回结果
onBluetoothDeviceFound()
},
fail: (res) => {
console.log(res, "搜索蓝牙失败");
}
});
}
//寻找到新设备的事件的回调函数
const onBluetoothDeviceFound = () => {
wx.onBluetoothDeviceFound((res) => {
console.log('onBluetoothDeviceFound', res);
res.devices.forEach(device => {
if (!device.name && !device.localName) {
return
}
console.log('filter onBluetoothDeviceFound start', devices, devices.value);
// 蓝牙数组
const foundDevices = devices.value;
const idx = findArrItem(foundDevices, device.deviceId);
const data = {};
if (idx === -1) {
foundDevices.push(device);
} else {
foundDevices[idx] = device;
}
console.log('filter onBluetoothDeviceFound end', devices.value);
devices.value = foundDevices
})
})
}
//重复搜索时,判断设备是否已经存在过滤掉
const findArrItem = (arr, id) => {
let index = -1;
for (let i in arr) {
if (arr[i].deviceId == id) {
index = i;
}
}
return index;
}
//停止蓝牙搜索
const stopBluetoothDevicesDiscovery = () => {
wx.stopBluetoothDevicesDiscovery({
success() {
console.log('停止蓝牙搜索success')
},
fail() {
console.log('停止蓝牙搜索fail')
}
})
}
//绑定设备
const setBindDevice = (item) => {
console.log(item);
//创建连接,测试设备是否可以读,可写
createBLEConnection(item);
}
//低功耗蓝牙设备连接
const createBLEConnection = (item, callback) => {
console.log('createBLEConnection');
wx.createBLEConnection({
deviceId: item.deviceId,
timeout: 15000,
success: (res) => {
console.log('蓝牙连接成功');
bindDevice.value = item
//如果蓝牙设备write没定义,说明是新设备需要执行
if (platform.value == 'android') {
if (item.write == undefined) {
//检查该蓝牙设备是否有写入权限,并保存参数,以便发送数据
getBLEDeviceServices(item.deviceId, callback);
} else {
callback ? callback() : ''
}
} else {
getBLEDeviceServices(item.deviceId, callback);
}
},
fail: (res) => {
console.log("蓝牙连接失败:", res);
}
})
}
//获取蓝牙设备所有服务(service)
const getBLEDeviceServices = (deviceId, callback) => {
wx.getBLEDeviceServices({
deviceId,
success: (res) => {
console.log('getBLEDeviceServices', res.services)
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].isPrimary) {
getBLEDeviceCharacteristics(deviceId, res.services[i].uuid, callback)
return
}
}
},
fail: (res) => {
console.log("获取蓝牙服务失败:" + JSON.stringify(res))
}
})
}
//获取蓝牙设备某个服务中所有特征值(characteristic)
const getBLEDeviceCharacteristics = (deviceId, serviceId, callback) => {
wx.getBLEDeviceCharacteristics({
deviceId,
serviceId,
success: (res) => {
console.log('getBLEDeviceCharacteristics success', res.characteristics)
for (let i = 0; i < res.characteristics.length; i++) {
let item = res.characteristics[i];
let _uuid = item.uuid;
let bindDevices = bindDevice.value;
// 读取低功耗蓝牙设备的特征值的二进制数据值 注意:必须设备的特征值支持 read 才可以成功调用。
if (item.properties.read) {
bindDevices.read = true;
}
//向低功耗蓝牙设备特征值中写入二进制数据。注意:必须设备的特征值支持 write 才可以成功调用。
if (item.properties.write) {
bindDevices.serviceId = serviceId;
bindDevices.characteristicId = _uuid;
bindDevices.write = true;
callback ? callback() : ''
}
//启用低功耗蓝牙设备特征值变化时的 notify 功能,使用characteristicValueChange事件
if (item.properties.notify || item.properties.indicate) {
wx.notifyBLECharacteristicValueChange({
deviceId,
serviceId,
characteristicId: _uuid,
state: true,
})
}
//设置当前选中的蓝牙设备,包括是否可读写属性采集
bindDevice.value = bindDevices
}
},
fail(res) {
console.error('获取特征值失败:', res)
}
})
}
//发送数据
const sendStr = (device, bufferstr, success, fail) => {
console.log('sendStr', device);
wx.writeBLECharacteristicValue({
deviceId: device.deviceId,
serviceId: device.serviceId,
characteristicId: device.characteristicId,
value: bufferstr,
success: function (res) {
success(res);
console.log('sendStr', bufferstr)
},
failed: function (res) {
fail(res)
console.log("数据发送失败:" + JSON.stringify(res))
},
// complete: function(res) {
// console.log("发送完成:" + JSON.stringify(res))
// }
})
}
//点击打印
const clickPrint = () => {
console.log('clickPrint');
// order = '', //传递进去的打印内容
const device = bindDevice.value; //可存到后台或者本地缓存来读取传递进来
//避免连接过多,先断开所有连接
wx.closeBluetoothAdapter({
success: () => {
console.log(274, 'clickPrint');
//初始化蓝牙
wx.openBluetoothAdapter({
success: (res) => {
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: false,
complete: (res) => {
callbackOpenBluetooth();
stopBluetoothDevicesDiscovery();
}
});
},
fail: (res) => {
if (res.errCode === 10001) {
console.log('蓝牙未开启!');
} else {
console.log('蓝牙初始化失败!');
}
}
})
}
});
//直接打印
let callbackConnected = () => {
console.log('数据生成中...');
console.log(device, 'device');
writeBLECharacteristicValue(device);
};
//检查设备是否连接
let callbackOpenBluetooth = () => {
console.log('检查设备是否连接...');
getConnectedBluetoothDevices(device, callbackConnected);
};
}
//获取已经连接的蓝牙设备,并开始打印
const getConnectedBluetoothDevices = (device, callback) => {
console.log('getConnectedBluetoothDevices', device, callback);
wx.getConnectedBluetoothDevices({
services: [device.serviceId],
success(res) {
console.log('getConnectedBluetoothDevices success', res, device);
let devices = res.devices;
let index = findArrItem(devices, device.deviceId);
if (index === -1) {
//如果该设备不是连接的,断开所有蓝牙连接
for (let i in devices) {
closeBLEConnection(devices[i]);
}
//重新连接该设备,重新点击打印,再次发送数据给打印机
createBLEConnection(device, callback);
} else {
callback ? callback() : ''
}
}
})
}
//小票打印机打印
const writeBLECharacteristicValue = (device) => {
console.log(device, 'device');
let arrPrint = [];
//初始化打印机
arrPrint.push(util.sendDirective([0x1B, 0x40])); //16进制
//居中对齐
arrPrint.push(util.sendDirective([0x1B, 0x61, 0x01])); //居中
//正文
arrPrint.push(util.sendDirective([0x1B, 0x0E]));
arrPrint.push(util.hexStringToBuff("\n标题\n\n"));
arrPrint.push(util.sendDirective([0x1B, 0x14]));
arrPrint.push(util.hexStringToBuff('商家:某某某某信息科技有限公司' + "\n\n"));
arrPrint.push(util.hexStringToBuff("--------------------------------\n\n"));
arrPrint.push(util.hexStringToBuff('扫二维码完成开票' + "\n\n\n"));
//printImgT(设备,'绘制的内容')
printInfo(device, arrPrint, () => printImgT(device, 'a surprise packet'));
}
//打印二维码
const printImgT = (device, text) => { //小票打印
console.log('printImgT', Buffer);
const ctx = wx.createCanvasContext('canvas');
ctx.clearRect(0, 0, 160, 160);
drawQrcode({
canvasId: 'canvas',
text: String(text),
width: 160,
height: 160,
callback(e) {
setTimeout(() => {
// 获取图片数据
wx.canvasGetImageData({
canvasId: 'canvas',
x: 0,
y: 0,
width: 160,
height: 160,
success(res) {
let arr = convert4to1(res.data);
let data = convert8to1(arr);
// 居中对齐 打印光栅位图
const cmds = [].concat([27, 97, 1], [29, 118, 48, 3, 20, 0, 160, 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.hexStringToBuff("\n"));
arrPrint.push(util.sendDirective([0x1B, 0x61, 0x01])); //居中
arrPrint.push(util.hexStringToBuff("二维码有效时间:2024-01-15 16:39:48\n\n"));
arrPrint.push(util.hexStringToBuff("--------------------------------\n\n"));
arrPrint.push(util.hexStringToBuff(util.printTwoData("申请日期:", '2024-01-15 16:39:48')+'\n'));
arrPrint.push(util.hexStringToBuff(util.printTwoData("项目名称:", 'test')+'\n'));
arrPrint.push(util.hexStringToBuff(util.printTwoData("金额:", '1.23')+'\n'));
arrPrint.push(util.hexStringToBuff(util.printTwoData("税率:", '免税')+'\n'));
arrPrint.push(util.hexStringToBuff(util.printTwoData("税额:", '1.23')+'\n'));
arrPrint.push(util.hexStringToBuff(util.printTwoData("价税合计:", '1.23')+'\n'));
arrPrint.push(util.hexStringToBuff("--------------------------------\n"));
arrPrint.push(util.hexStringToBuff("\n如您对开票有任何疑问请咨询商家\n"));
arrPrint.push(util.hexStringToBuff("\n咨询电话:11111111111\n\n"));
arrPrint.push(util.hexStringToBuff("\n"));
arrPrint.push(util.hexStringToBuff("\n"));
printInfo(device, arrPrint);
}
})
}, 3000);
}
});
}
const printInfo = (device, arr, callback) => {
if (arr.length > 0) {
sendStr(device, arr[0], function (success) {
arr.shift();
printInfo(device, arr, callback);
}, function (error) {
console.log(error);
});
} else {
callback ? callback() : '';
}
}
//4合1
const 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;
}
//8合1
const 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;
}
</script>
大家创建一个项目直接复制就可以啦