uniapp 与蓝牙设备收发指令详细步骤(完整项目版)

阅读前须知

1、若已知蓝牙设备的 deviceId、serviceId、以及读写特征值,可以直接从第7点开始阅读
2、文档中各函数的详细属性、回调函数等介绍内容,可以查看官网文档:uniapp 低功耗蓝牙连接
3、与蓝牙设备之间收发数据格式必须为 ArrayBuffer
4、本文中与蓝牙设备收发数据时,数据包的长度为20 字节,不够 20 字节的补 0

1、初始化蓝牙模块
uni.openBluetoothAdapter({
	success(res) {
		console.log('初始化蓝牙成功')
		console.log(res)
	},
	fail(err) {
		console.log('初始化蓝牙失败')
		console.error(err)
	}
})
2、搜索附近可连接的蓝牙设备

uni.startBluetoothDevicesDiscovery()比较耗费系统资源,建议搜索完成后调用stopBluetoothDevicesDiscovery()结束搜索。

uni.startBluetoothDevicesDiscovery({
	allowDuplicatesKey: false,
	interval: 0,
	success: (res) => {
		console.log("执行搜索成功的回调")
	},
	fail: (error) => {
		console.log(error)
	}
})

若需要过滤搜索出来的蓝牙设备,可以设置services属性进行过滤

在这里插入图片描述

3、搜索附近可连接的蓝牙设备

uni.getBluetoothDevices()获取在蓝牙模块生效期间所有已发现的蓝牙设备。包括已经和本机处于连接状态的设备

uni.getBluetoothDevices({
	success: function(res) {
		console.log(res)
	},
	fail: function() {
		console.log("获取蓝牙设备列表失败")
	}
})

到这一步,已经能拿到附近所有的蓝牙设备列表,下面开始进行连接。

4、连接低功耗蓝牙设备

前提条件:

  1. 蓝牙设备支持低功耗协议(BLE)
  2. 拿到设备的deviceId
uni.createBLEConnection({
	deviceId: this.deviceId,  // 在第 3 步可以拿到蓝牙的 deviceId 的值
	success: (res) => {
		console.log("连接成功", res)
		
		// 在这里可以执行获取蓝牙设备的所有服务,若获取失败可以使用 setTimeout
	},
	fail: (error) => {
		console.log("连接失败", error)
	}
})
5、获取蓝牙设备的所有服务
uni.getBLEDeviceServices({
	deviceId: this.deviceId,  // 在第 3 步可以拿到蓝牙的 deviceId 的值
	success: (res) => {
		console.log('成功获取蓝牙设备的所有服务', res)
		
		// 这里可以拿到蓝牙设备的 serviceId
	}
})
6、获取蓝牙设备某个服务中所有特征值(characteristic)
uni.getBLEDeviceCharacteristics({
	deviceId: this.deviceId,  // 在第 3 步可以拿到蓝牙的 deviceId 的值
	serviceId: this.serviceId,  // 在第 5 步可以拿到蓝牙的 serviceId 的值
	success: (res) => {
		console.log('获取 characteristic 成功', res)
		
		// 在这里可以获取到这个服务的所有特征值,需要确定哪些特征值是此次使用的
		// 一般这里可以拿到两个特征值:写characteristic、读characteristic
		// 接下来这里可以根据拿到的“读characteristic”开启 notify
	},
	fail: (res) => {
		console.log('获取 characteristic 失败', res)
	}
})
7、启动 notify 功能监听蓝牙设备回传信息

注意:必须设备的特征值支持 notify 或者 indicate 才可以成功调用

uni.notifyBLECharacteristicValueChange({
	state: true,
	deviceId: this.deviceId,  // 在第 3 步可以拿到蓝牙的 deviceId 的值
	serviceId: this.serviceId,  // 在第 5 步可以拿到蓝牙的 serviceId 的值
	characteristicId: this.readCharacteristic,  // 在第 6 步可以拿到蓝牙的 characteristic 的值,这里使用的是 “读characteristic”
	success(res) {
		console.log("开启 notify 功能成功...")
		
		// 必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送
		uni.onBLECharacteristicValueChange(res => {
			let resHex = ab2hex(res.value)  // 将蓝牙设备回传的内容进行解析
			console.log("接收到回传内容:", resHex)  // 若需要,可参考第 9 点解析响应包的源码
			
			// 蓝牙设备会分多次回传数据,并且都可以在这里监听到
			// 这里可以执行一个处理所有回传结果的函数
		})
	},
	fail(err) {
		console.log("监听失败,发生错误", err)
	}
})


// 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('')
}

到这里,已经完成了与低功耗蓝牙设备连接、蓝牙设备回传数据的监听。

8、向蓝牙设备发送指令

假设,存在一个获取蓝牙设备电量的指令如下:

向蓝牙设备发送数据格式:

起始码数据类型数据
0xSA0x010x00,0x00,…,0x00

蓝牙设备回传数据格式:

起始码数据类型结果电量空数据
0xRA0x010x010x140x00,0x00,…,0x00
let buffer = generate_command(0xSA, 0x01)

uni.writeBLECharacteristicValue({
	deviceId: this.deviceId,  // 在第 3 步可以拿到蓝牙的 deviceId 的值
	serviceId: this.serviceId,  // 在第 5 步可以拿到蓝牙的 serviceId 的值
	characteristicId: this.writeCharacteristicId,  // 在第 6 步可以拿到蓝牙的 characteristic 的值,这里使用的是 “写characteristicId”
	value: buffer,  // buffer 的格式为 ArrayBuffer
	success(res) {
		console.log('指令下发成功', res)
	},
	fail(err) {
		console.log('指令发送失败', err)
	}
})


/**
 * 生成 ArrayBuffer 格式的数据,可以直接用于给蓝牙设备发送数据
 * @param {Object} startCode 起始码
 * @param {Object} dataType 数据类型
 * @param {Object} sentData 发送给蓝牙的数据数组,例如:[0x12,0x01]
 */
function generate_command(startCode, dataType, sentData) {
	let buffer = new ArrayBuffer(20)
	let dataView = new DataView(buffer)
	dataView.setUint8(0, startCode)
	dataView.setUint8(1, dataType)
	let _beforeIndex = 2
	
	if(sentData) {
		for (var k = 0; k < sentData.length; k++) {
			dataView.setUint8(k + _beforeIndex, sentData[k])
		}
		_beforeIndex += sentData.length
	}
	return buffer
}

当指令发送成功后,在第 7 点中可以接收到蓝牙设备的响应包。否则,都视作为蓝牙接收数据失败!

9、附加:解析蓝牙响应数据包

在第 7 点中接受到响应的数据包后,仍然不是可以直观看出数据真实信息的格式,因此需要再次转换。

// responseData 的值为第 7 点中的 resHex
function parse_blue_response(responseData) {
	const dataList = responseData.match(/.{1,2}/g)
	const [resCode, resType, resResult] = dataList.splice(0, 3)
	// resCode:响应包起始码;
	// resType:响应包数据类型
	// resResult:响应包结果
	// dataList:其他响应数据 + 空数据,Array 格式数据
	return [resCode, resType, String(resResult), dataList]
}

10、附加:将上一步的 Array 解析成 number
function array16_to_number(arrayValue) {
	const newArray = arrayValue.filter(item => String(item) !== '00' || String(item) !== '0')
	const _number16 = newArray.map(hex => parseInt(hex, 16).toString(16)).join('')
	return parseInt(`0x${_number16}`)
}

如第 8 点,指令返回的电量结果为0x14,经过转换的得到值为20

在这里插入图片描述

!!!关于array16_to_number函数的bug说明uniapp解析蓝牙设备响应数据bug

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值