uniapp连接蓝牙打印小票(附加demo)

本文详细介绍了如何在UniApp中使用JavaScript进行蓝牙连接,搜索蓝牙设备,获取和服务的特征值,并实现打印小票的功能。步骤包括初始化蓝牙、搜索设备、连接设备、获取服务和特征值以及发送和接收数据。
摘要由CSDN通过智能技术生成

一、根据需求去实现的打印小票,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>

大家创建一个项目直接复制就可以啦

  • 12
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值