微信小程序连接蓝牙低功耗设备

连接步骤 

  1. 初始化蓝牙
    // 蓝牙初始化   
    	openBluetooth() {
    		let that = this
    		wx.openBluetoothAdapter({
    			success: (res) => {
    				console.log(res);
    				that.getBluetoothState();
    			},
    			fail: (err) => {
    				console.log(err);
    			}
    		})
    	}
  2. 停止搜索附近的蓝牙外围设备
    // 停止搜索附近的蓝牙外围设备
    	stopBluetoothDevicesDiscovery() {
    		wx.stopBluetoothDevicesDiscovery({
    			success: (res) => {
    				console.log('停止搜索蓝牙设备:', res.errMsg);
    				wx.offBluetoothDeviceFound()
    			},
    			fail: (res) => {
    				console.log('停止搜索蓝牙设备失败:', res.errMsg);
    			}
    		})
    	}
  3. 获取本机蓝牙适配器状态
    //  获取本机蓝牙适配器状态
    	getBluetoothState() {
    		let that = this
    		wx.getBluetoothAdapterState({
    			success: (res) => {
    				console.log(res);
    				that.startBluetoothDevices()
    			},
    			fail: (err) => {
    				console.log(err);
    			}
    		})
    	}

  4. 开始搜寻附近的蓝牙外围设备
    // 开始搜寻附近的蓝牙外围设备
    	startBluetoothDevices() {
    		let that = this
    		wx.startBluetoothDevicesDiscovery({
    			powerLevel: 'high',
                services: ['主服务UUID'], // 不填则搜索周围所有设备
    			success: (res) => {
    				console.log("开始搜寻附近的蓝牙外围设备", res);
    				that.onBluetoothDeviceFound()
    			},
    			fail: (err) => {
    				console.log("开始搜寻附近的蓝牙外围设备", err);
    			}
    
    		})
    	}

    其中services属性是蓝牙设备的主服务UUID,需要设备能够广播出自己的主服务才能正常搜索到这类设备,不然就无法搜索到只能使用搜索周围设备的方案然后手动筛选。

  5. 开启监听搜索到新设备的事件
    // 发现外围设备
    	onBluetoothDeviceFound() {
    		let that = this
    		console.log("发现外围设备");
    		wx.onBluetoothDeviceFound(function (res) {
    			console.log("开锁", res);
    			// that.getBluetoothDevices()
    		})
    		
    	}

    onBluetoothDeviceFound这个方法是个事件监听,如果在筛选阶段找到的目标设备需要手动调用停止监听事件也就是上方定义的 “停止搜索附近的蓝牙外围设备”这个方法。

  6. 获取在蓝牙模块生效期间所有搜索到的蓝牙设备(包括以搜索到的)
    // 获取在蓝牙模块生效期间所有已发现的蓝牙设备
    	getBluetoothDevices() {
    		let that = this
    		wx.getBluetoothDevices({
    			success: (res) => {
    				// console.log(res);
    				that.getOtherDevices(res) // 手动筛选出目标数据
    			},
    			fail: (err) => {
    				console.log(err);
    			}
    		})
    	},

    在上述“开启监听搜索到新设备的事件”中为什么会将这个方法其注掉呢?因为是事件监听所以会一直被执行,如果嵌套调用会一直执行这个方法,一直获取周围的设备有设备进来就能被监听到获取到看似是没有问题,但是如果需要手动筛选符合条件的设备,就会一直执行这个方法,就会导致开启设备很慢。 既然这么的麻烦为什么还要用这个方法而不直接在监听中写逻辑呢?这个方式也是可行的,但是会存在搜索过的设备再次去搜索获取不到的情况。监听获取周围设备是一次只获取到单个设备,而getBluetoothDevices这个获取的是多个设备。

  7. 找到符合条件的设备
    // 找到符合条件的设备
    	clearOtherDevices(data) {
    		let that = this
    		let devicesLength = data.devices.length
            // 这里怎么去获取目标设备都行 我这里用的是for 也可以使用.find()
    		for (var i = 0; i < devicesLength; i++) {
                    if(条件){
    				that.createBLEConnection()
    				break;
    			}
    		}
    	},

    这里是寻找目标设备,但是如果我以知晓连接设备需要初始化蓝牙适配器并且也知道连接设备需要mac地址并填写在createBLEConnection这个API中的deviceId属性中,那为什么不能直接在初始化蓝牙适配器中直接去连接设备呢?这个方法是可行的,是个不错的想法,这边获取的deviceId是D4:AD:20:57:3F:E6这种的,安卓中这样使用是没有问题,但是IOS系统的deviceId是UUID的形式去连接而这中deviceId只有在搜索设备中才能获取到这中UUID形式的deviceId。既然IOS与安卓的deviceId不同那么我改如何去寻找目标设备呢?寻找目标设备可以按照固定格式的蓝牙名称匹配搜索,若蓝牙名称相同可以用已知设备的mac值匹配搜索,两个系统的deviceId不同可以根据搜索到设备列表的advertisData这个属性进行转化成D4:AD:20:57:3F:E6这种格式的mac值。

    const ArrayBufferToArray = (arrayBuffer) => {
    	return Array.prototype.slice.call(new Uint8Array(arrayBuffer));
    };
    let advertisData = ArrayBufferToArray(device.advertisData).slice(2, 8);
    console.log(advertisData.join(','));

    ps:同一个蓝牙设备不同的IOS设备获取的deviceId是不一样的!!

  8. 连接蓝牙低功耗设备
    // 蓝牙链接
    	createBLEConnection() {
    		let that = this;
    		wx.createBLEConnection({
    			deviceId: that.data.mac,
    			success: (res) => {
    				//停止搜索
    				that.stopBluetoothDevicesDiscovery();
    				that.getBLEDeviceServices()
    			},
    			fail: (err) => {
    				console.log('连接低功耗蓝牙失败,错误码:', err);
    			}
    		})
    	}

  9. 获取蓝牙低功耗设备所有服务
    // 获取服务
    	getBLEDeviceServices() {
    		let that = this
            let services = [];
    		wx.getBLEDeviceServices({
    			deviceId: that.data.mac,
    			success: (res) => {
    				console.log("获取服务成功", res);
                    services = res.services;
                    // 找到自己需要的主服务UUID
    
                   this.setData({
                      serviceId: res.services[1].serviceId
                    })
    			},
    			fail: (err) => {
    				console.log("获取服务失败", err);
    			}
    		})
    	}

  10. 获取蓝牙低功耗设备某个服务中所有特征
    // 获取某个服务下的所有特征值
    	getBLEDeviceCharacteristics() {
    		 let charactArray = [];
             let that = this
    
    		wx.getBLEDeviceCharacteristics({
    			deviceId: that.data.mac,
    			serviceId: that.data.serviceId, // 主服务UUID
    			success: (res) => {
    				console.log("服务下的所有特征值成功", res);
    				charactArray = res.characteristics;
                    if (charactArray.length <= 0) {
                      console.log('获取特征值失败,请重试!');
                      return;
                    }
                    for (var i = 0; i < charactArray.length; i++) {
                      // 获取可写的characteristicId
                      if (charactArray[i].properties.write === true) {
                        // console.log(charactArray[i].uuid);
                        that.setData({
                          characteristicId: charactArray[i].characteristicId
                        })
                      }
                      // 获取可监听的characteristicId
                      if (charactArray[i].properties.notify === true) {
                        // console.log(charactArray[i].uuid);
                        that.setData({
                          notifyId: charactArray[i].characteristicId
                        })
                      }
                    }
    				// 开启监听
    				that.notifyBLECharacteristicValueChange()
    				that.sendMy()
    			},
    			fail: (err) => {
    				console.log("服务下的所有特征值失败", err);
    			}
    		})
    	},

  11. 启用蓝牙低功耗设备特征值变化时的 notify 功能,订阅特征
    // 读数据
      notifyBLECharacteristicValueChange() {
        let that = this
        wx.notifyBLECharacteristicValueChange({
          state: true, //是否启用notify
          deviceId: that.data.devicesId,
          serviceId: that.data.serviceId,
          characteristicId: that.data.notifyId,
          //这个characteristicId是上面方法存的能读数据的uuid
          state: true,
          success: (res) => {
            console.log('notifyBLECharacteristicValueChange success:', res.errMsg, res);
            // console.log(JSON.stringify(res));
            that.onBLECharacteristicValueChange();
          },
        })
      },

  12. 监听蓝牙低功耗设备的特征值变化事件
    // 监听蓝牙特征值变化
      onBLECharacteristicValueChange() {
        let that = this
        wx.onBLECharacteristicValueChange(function (res) {
          let arrayBuffer = getApp().hex2ArrayBuffer(res.value)
          let arr = getApp().ArrayBufferToArray(arrayBuffer);
          let command = String(getApp().aesDecrypt(arr)).split(',');
          
          // 根据方法解析的数据判断设备的状态
          if (判断) {
            
          }
        });
      },

  13. 向蓝牙低功耗设备特征值中写入二进制数据
    // 写入
      writeToken() {
        let that = this;
        // 向蓝牙低功耗设备特征值中写入二进制数据
        wx.writeBLECharacteristicValue({
          deviceId: that.data.devicesId,
          serviceId: that.data.serviceId,
          characteristicId: that.data.characteristicId,
          value: that.data.value,
          writeType: that.data.writeType,
          success: (res) => {
            console.log("写入成功");
          },
          fail: (fail) => {
            console.log("写入失败", fail);
          },
        });
      },

    需要将写入的值转为ArrayBuffer类型的数据,如果是数组需要将数组中的复杂格式的值转为普通格式的然后再将数组转为ArrayBuffer类型。

工具类

 将字符串转换成ArrayBufer
/**
 * 将字符串转换成ArrayBufer
 * @param {字符串数据} str 
 */
const string2buffer = (str) => {
	let val = ""
	if (!str) return;
	let length = str.length;
	let index = 0;
	let array = []
	while (index < length) {
		array.push(str.substring(index, index + 2));
		index = index + 2;
	}
	val = array.join(",");
	// 将16进制转化为ArrayBuffer
	return new Uint8Array(val.match(/[\da-f]{2}/gi).map(function (h) {
		return parseInt(h, 16)
	})).buffer
}
将ArrayBuffer转换成字符串
/**
 * 将ArrayBuffer转换成字符串
 * @param {buffer数据} buffer 
 * @return {字符串数据}
 */
const ab2hex = (buffer) => {
	var hexArr = Array.prototype.map.call(
		new Uint8Array(buffer),
		function (bit) {
			return ('00' + bit.toString(16)).slice(-2)
		}
	)
	return hexArr.join('');
}
数组转ArrayBuffer
/**
 * 数组转ArrayBuffer
 * @param {数组} array 
 */
const ArrayToArrayBuffer = (array) => {
	return new Uint8Array(array).buffer;
};
ArrayBuffer转数组
/**
 * ArrayBuffer转数组
 * @param {arrayBuffer数组} arrayBuffer 
 * @return {数组}
 */
const ArrayBufferToArray = (arrayBuffer) => {
	return Array.prototype.slice.call(new Uint8Array(arrayBuffer));
};
 字符串转byte
// 字符串转byte
function stringToBytes(str) {
	var array = new Int8Array(str.length)
	for (var i = 0; i < str.length; i++) {
		array[i] = str.charCodeAt(i)
	}
	return array.buffer
}
ArrayBuffer转Str
// ArrayBuffer转Str
function ArrayBufferToStr(value) {
	var buffer = value
	var dataview = new DataView(buffer)
	var ints = new Uint8Array(buffer.byteLength)
	var str = ''
	for (var i = 0; i < ints.length; i++) {
		str += String.fromCharCode(dataview.getUint8(i))
	}
	return str
}

结语

在整个流程中的监听在使用完毕后记得关闭,会有相应的关闭监听事件的API。此外在调试过程中会有遇到监听事件没有响应的情况,请查看写法与是否开启响应的前置条件,例如写入数据时成功写入数据才会有监听结果,箭头函数好像会有问题所以用的function。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
微信小程序可以通过使用蓝牙 API 来读取蓝牙设备返回的数据。下面是一个简单的示例代码,演示如何读取蓝牙设备的数据: ```javascript // 开始搜索蓝牙设备 wx.startBluetoothDevicesDiscovery({ success: function (res) { // 监听蓝牙设备发现事件 wx.onBluetoothDeviceFound(function (devices) { // 遍历发现的蓝牙设备列表 devices.devices.forEach(function (device) { // 判断是否是目标设备 if (device.deviceId === 'YOUR_DEVICE_ID') { // 停止搜索蓝牙设备 wx.stopBluetoothDevicesDiscovery(); // 连接目标设备 wx.createBLEConnection({ deviceId: 'YOUR_DEVICE_ID', success: function (res) { // 监听蓝牙连接状态改变事件 wx.onBLEConnectionStateChange(function (res) { if (!res.connected) { console.log('蓝牙设备已断开连接'); } }); // 获取蓝牙设备的服务列表 wx.getBLEDeviceServices({ deviceId: 'YOUR_DEVICE_ID', success: function (res) { // 遍历服务列表 res.services.forEach(function (service) { // 判断是否是目标服务 if (service.uuid === 'YOUR_SERVICE_UUID') { // 获取服务的特征值列表 wx.getBLEDeviceCharacteristics({ deviceId: 'YOUR_DEVICE_ID', serviceId: service.uuid, success: function (res) { // 遍历特征值列表 res.characteristics.forEach(function (characteristic) { // 判断是否是目标特征值 if (characteristic.uuid === 'YOUR_CHARACTERISTIC_UUID') { // 开始监听蓝牙设备的特征值变化 wx.onBLECharacteristicValueChange(function (res) { // 处理接收到的数据 var data = ab2hex(res.value); console.log('收到数据:', data); }); // 启用低功耗蓝牙设备特征值变化通知 wx.notifyBLECharacteristicValueChange({ deviceId: 'YOUR_DEVICE_ID', serviceId: service.uuid, characteristicId: characteristic.uuid, state: true, success: function (res) { console.log('已开启数据接收'); } }); } }); } }); } }); } }); } }); } }); }); } }); // 将 ArrayBuffer 转为十六进制字符串 function ab2hex(buffer) { var hexArr = Array.prototype.map.call(new Uint8Array(buffer), function (bit) { return ('00' + bit.toString(16)).slice(-2); }); return hexArr.join(''); } ``` 在示例代码中,你需要将 `YOUR_DEVICE_ID` 替换为目标蓝牙设备的 ID,将 `YOUR_SERVICE_UUID` 替换为目标服务的 UUID,将 `YOUR_CHARACTERISTIC_UUID` 替换为目标特征值的 UUID。 请注意,读取蓝牙设备返回的数据需要在小程序蓝牙权限设置中开启并获取用户授权。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值