微信小程序连接蓝牙打印小票

001:格式

<script>
	const LAST_CONNECTED_DEVICE = 'last_connected_device'
	import PrinterJobs from '../../common/printer/printerjobs'
	import printerUtil from '../../common/printer/printerutil'

	function inArray(arr, key, val) {
		for (let i = 0; i < arr.length; i++) {
			if (arr[i][key] === val) {
				return i
			}
		}
		return -1
	}

	// ArrayBuffer转16进度字符串示例
	function ab2hex(buffer) {
		const hexArr = Array.prototype.map.call(
			new Uint8Array(buffer),
			function(bit) {
				return ('00' + bit.toString(16)).slice(-2)
			}
		)
		return hexArr.join(',')
	}

	function str2ab(str) {
		// Convert str to ArrayBuff and write to printer
		let buffer = new ArrayBuffer(str.length)
		let dataView = new DataView(buffer)
		for (let i = 0; i < str.length; i++) {
			dataView.setUint8(i, str.charAt(i).charCodeAt(0))
		}
		return buffer;
	}
	export default {
		data() {
			return {
                devices: [],
            }
        },
        onLoad(e) {
			const lastDevice = uni.getStorageSync(LAST_CONNECTED_DEVICE);
			this.lastDevice = lastDevice
			// 初始化蓝牙
			this.openBluetoothAdapter()
		},
    }

</script>

1、初始化蓝牙

// 初始化蓝牙模块
			openBluetoothAdapter() {
				if (!uni.openBluetoothAdapter) {
					uni.showModal({
						title: this.$t('wechat.w102'), //'提示',
						content: this.$t('wechat.w226') //'当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
					})
					return
				}
				uni.openBluetoothAdapter({
					success: (res) => {
						console.log('openBluetoothAdapter success', res)
						// 搜寻附近的蓝牙
						this.startBluetoothDevicesDiscovery()
					},
					fail: (res) => {
						console.log('openBluetoothAdapter fail', res)
						if (res.errCode === 10001) {
							uni.showModal({
								title: this.$t('wechat.w227'), //错误
								content: this.$t('wechat.w228'), //'未找到蓝牙设备, 请打开蓝牙后重试。',
								showCancel: false
							})
							// 监听蓝牙适配器状态变化事件
							uni.onBluetoothAdapterStateChange((res) => {
								console.log('onBluetoothAdapterStateChange', res)
								// available:蓝牙适配器是否可用
								if (res.available) {
									// 取消监听,否则stopBluetoothDevicesDiscovery后仍会继续触发onBluetoothAdapterStateChange,
									// 导致再次调用startBluetoothDevicesDiscovery
									uni.onBluetoothAdapterStateChange(() => {});
									// 开始搜寻附近的蓝牙外围设备
									this.startBluetoothDevicesDiscovery()
								}
							})
						}
					}
				})
				uni.onBLEConnectionStateChange((res) => {
					// 该方法回调中可以用于处理连接意外断开等异常情况
					console.log('onBLEConnectionStateChange',
						`device ${res.deviceId} state has changed, connected: ${res.connected}`)
					this.connected = res.connected
					if (!res.connected) {
						uni.showModal({
							title: this.$t('wechat.w227'), //错误
							content: this.$t('wechat.w229'), //蓝牙连接已断开
							showCancel: false
						})
					}
				});
			},

2.搜索附近蓝牙设备

// 开始搜寻附近的蓝牙外围设备
			startBluetoothDevicesDiscovery() {
				if (this._discoveryStarted) {
					return
				}
				this._discoveryStarted = true
				uni.startBluetoothDevicesDiscovery({
					success: (res) => {
						console.log('startBluetoothDevicesDiscovery success111', res)
						// 监听寻找到新设备的事件
						this.onBluetoothDeviceFound()
					},
					fail: (res) => {
						console.log('startBluetoothDevicesDiscovery fail', res)
					}
				})
			},

3.监听寻找到新设备的事件

// 监听寻找到新设备的事件
			onBluetoothDeviceFound() {
				uni.onBluetoothDeviceFound((res) => {
					console.log('寻找设备', res)
					res.devices.forEach(device => {
						if (!device.name && !device.localName) {
							return
						}
						const foundDevices = this.devices
						const idx = inArray(foundDevices, 'deviceId', device.deviceId)
						const data = {}
						if (idx === -1) {
							this.$set(this.devices, `${foundDevices.length}`, device)
						} else {
							this.$set(this.devices, `${idx}`, device)
						}
						// console.log(this.devices)
					})
				})
			},

4.点击连接蓝牙

// 点击链接蓝牙
			createBLEConnection(e) {
				console.log('点击连接蓝牙', e)
				const deviceId = e.deviceId
				const name = e.name
				this._createBLEConnection(deviceId, name)
			},
// 连接蓝牙设备
			_createBLEConnection(deviceId, name) {
				this.$myToast(this.$t('wechat.w224'), 'loading') //连接设备中
				// 连接低功耗蓝牙设备
				uni.createBLEConnection({
					deviceId, // 用于区分设备的 id
					success: () => {
						console.log('createBLEConnection success', this.devices);
						this.devices.forEach((item, index) => {
							this.$set(this.devices[index], 'isShowConnect', false)
							if (item.deviceId == deviceId) {
								this.$set(this.devices[index], 'isShowConnect', true)
							}
						})
						this.$myToast(this.$t('wechat.w225'), 'success') //设备连接成功
						this.connected = true
						this.isConnected = false
						this.name = name
						this.deviceId = deviceId

						//延迟1.5s获取设备的services
						setTimeout(() => {
							// 获取蓝牙设备所有服务(service)
							this.getBLEDeviceServices(deviceId)
						}, 3000);

						// 最后连接设备
						uni.setStorage({
							key: LAST_CONNECTED_DEVICE,
							data: name + ':' + deviceId
						})
					},
					complete() {
						uni.hideLoading()
					},
					fail: (res) => {
						// 连接蓝牙接口调用失败
						console.log('createBLEConnection fail', res)
					}
				})
				// 已经找到需要的蓝牙设备,停止搜寻附近的蓝牙外围设备
				this.stopBluetoothDevicesDiscovery()
			},
// 已经找到需要的蓝牙设备,停止搜寻附近的蓝牙外围设备
            stopBluetoothDevicesDiscovery() {
				    uni.stopBluetoothDevicesDiscovery({
					    complete: () => {
						    // console.log('stopBluetoothDevicesDiscovery')
						    this._discoveryStarted = false
					    }
				    })
			},

5.获取蓝牙设备所有服务

// 获取蓝牙设备所有服务(service)
			getBLEDeviceServices(deviceId) {
				uni.getBLEDeviceServices({
					deviceId,
					success: (res) => {
						console.log('获取蓝牙设备所有服务getBLEDeviceServices', res)
						for (let i = 0; i < res.services.length; i++) {

							// #ifdef MP-WEIXIN				
    						if (res.services[i].isPrimary) {                                       
                                this.getBLEDeviceCharacteristics(deviceId,res.services[i].uuid)
								return
							}
							// #endif
							// #ifdef APP-PLUS
							if (res.services[i].uuid === '0000FF00-0000-1000-8000-00805F9B34FB') {
								console.log('App的服务序号', res.services[i].uuid)
								this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid)
								return
							}
							// #endif

						}
					}
				})
			},

6.获取特征值

/*
				获取蓝牙设备某个服务中所有特征值(characteristic)
				characteristic:
					uuid:蓝牙设备特征值的 uuid
					properties:该特征值支持的操作类型
			*/
			getBLEDeviceCharacteristics(deviceId, serviceId) {
				uni.getBLEDeviceCharacteristics({
					// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
					deviceId,
					// 这里的 serviceId(蓝牙服务 uuid) 需要在 getBLEDeviceServices 接口中获取
					serviceId,
					success: (res) => {
						console.log('特征值getBLEDeviceCharacteristics success', deviceId, serviceId, res, res
							.characteristics)
						// 这里会存在特征值是支持write,写入成功但是没有任何反应的情况
						// 只能一个个去试
						// characteristics:设备服务列表
						for (let i = 0; i < res.characteristics.length; i++) {
							const item = res.characteristics[i]
							if (item.properties.write) {
								this.canWrite = true
								this._deviceId = deviceId
								this._serviceId = serviceId
								this._characteristicId = item.uuid
								break;
							}
						}
					},
					fail(res) {
						console.error('getBLEDeviceCharacteristics', res)
					}
				})
			},

7.点击打印写入数据

// 点击打印:写入数据
			writeBLECharacteristicValue() {
				this.isLoading = true
				setTimeout(() => {
					this.isDisabled = false
					this.isLoading = false
				}, 3000)
				let printerJobs = new PrinterJobs();
				const {
					channels,
					header,
					dataList
				} = this.printInfo
				console.log('通道数据', dataList)
				let title = ''
				header.forEach(item => {
					title = `${item.name}  `
				})
				// 要打印的头部信息
				printerJobs
					.setAlign('ct')
					.setSize(2, 2)
					.print(this.$t('wechat.w221')) //'记录报告'
					.setSize(0, 0)
					.print()
					.setAlign('lt')
					.setSize(1, 1)
					.print(`${this.$t('wechat.w51')}:${this.info.name}`) //设备名称
					.print(`${this.$t('wechat.w76')}:${this.info.modelName}`) //设备型号
					.print(`${this.$t('wechat.w46')}:${this.info.deviceSerial}`) //序列号
					.print(`${this.$t('wechat.w100')}:${this.userInfo.relName}`) //用户名
					.print(`${this.$t('wechat.w101')}:${this.remark}`) //备注
				if (this.isEn) {
					channels.forEach(item => {
						printerJobs.print(`${item.name}(Max):${item.max}${item.unitIcon}`)
							.print(`${this.$t('wechat.w148')}:${this.$timestampToTimeEn(item.maxDate)}`) //时间
							.print(`${item.name}(Min):${item.min}${item.unitIcon}`)
							.print(`${this.$t('wechat.w148')}:${this.$timestampToTimeEn(item.minDate)}`) //时间
					})
				} else {
					channels.forEach(item => {
						printerJobs.print(`${item.name}(Max):${item.max}${item.unitIcon}`)
							.print(`${this.$t('wechat.w148')}:${this.$timestampToTime2(item.maxDate)}`) //时间
							.print(`${item.name}(Min):${item.min}${item.unitIcon}`)
							.print(`${this.$t('wechat.w148')}:${this.$timestampToTime2(item.minDate)}`) //时间
					})
				}

				printerJobs.print(printerUtil.fillLine())
					.setSize(1, 1)
				let titleStr = ''
				header.forEach((item, index) => {
					titleStr = titleStr + `${index==0?'':'    '}` + `${item.name}`
				})
				printerJobs.print(printerUtil.inline(this.$t('wechat.w222'),
					`${titleStr}`)) //记录时间

				// 打印'----------------'
				printerJobs.print(printerUtil.fillLine())
				// 要打印的内容
				dataList.forEach(item => {
					let str = ''
					header.forEach((item2, index2) => {
						// 暂无
						str = str + `${index2==0?'':'  '}` +
							`${item[item2.columnName]?item[item2.columnName].toFixed(2):this.$t('wechat.w71empty')}`
					})
					if (this.isEn) {
						printerJobs.print(printerUtil.inline(`${this.$timestampToTimeEn2(item.dataTime)}`,
							`${str}`))
					} else {
						printerJobs.print(printerUtil.inline(`${this.$timestampToTime3(item.dataTime)}`,
							`${str}`))
					}
					// console.log(`${item.dataTime}`, str);
				})
				// 结尾
				printerJobs.println()
					.print(`${this.$t('wechat.w223')}:`) //'签名
					.println()
					.println()


				let buffer = printerJobs.buffer();
				// console.log('ArrayBuffer', 'length: ' + buffer.byteLength, ' hex: ' + ab2hex(buffer));
				// 1.并行调用多次会存在写失败的可能性
				// 2.建议每次写入不超过20字节
				// 分包处理,延时调用
				const maxChunk = 20;
				const delay = 40;
				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);
					// subPackage:参数
					setTimeout(this._writeBLECharacteristicValue, j * delay, subPackage);
				}
			},
			// 向低功耗蓝牙设备特征值中写入二进制数据。注意:必须设备的特征值支持 write 才可以成功调用。
			_writeBLECharacteristicValue(buffer) {
				uni.writeBLECharacteristicValue({
					deviceId: this._deviceId, // 蓝牙设备 id
					serviceId: this._serviceId, // 蓝牙特征值对应服务的 uuid
					characteristicId: this._characteristicId, // 蓝牙特征值的 uuid
					value: buffer, // 蓝牙设备特征值对应的二进制值
					success(res) {
						console.log('writeBLECharacteristicValue success', res)
					},
					fail(res) {
						console.log('writeBLECharacteristicValue fail', res)
					}
				})
			},

8.离开关闭蓝牙

//关闭蓝牙
        onUnload() {
			this.closeBluetoothAdapter()
		},

        closeBluetoothAdapter() {
				uni.closeBluetoothAdapter()
				this._discoveryStarted = false
		},

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值