赞
踩
//初始化蓝牙模块 clickbtn() { var that = this // 初始化蓝牙模块 wx.openBluetoothAdapter({ success: function (res) { // 获取蓝牙适配器状态 that.getBluetoothAdapterState() }, fail: function (res) { if (res.errCode == 10001) { //手机蓝牙不可用 // console.log('手机蓝牙不可用') wx.showToast({ title: '手机蓝牙不可用,请开启蓝牙再试~', icon: 'none', duration: 2000 }) } } }) },
在初始化蓝牙模块的时候我遇到了第一个问题,可谓出师不利,在我初始化手机上蓝牙模块的时候,wx.openBluetoothAdapter这个api一直调用失败,说我手机没有打开蓝牙,可是我检查了好几遍,手机上的蓝牙我是开启了的,代码也没啥问题,手动狗头。最后面向百度编程,才得知,当你使用苹果手机的时候(安卓的没试过),光打开设置了里面的蓝牙是不够的,还得将设置–>微信–>蓝牙打开才OK。
//获取本机蓝牙适配器状态 //检测本机蓝牙是否可用 getBluetoothAdapterState() { var that = this //获取本机蓝牙适配器状态 wx.getBluetoothAdapterState({ success: function (res2) { if (res2.errMsg == 'getBluetoothAdapterState:ok') { //搜寻附近的蓝牙设备 that.startBluetoothDevicesDiscovery() } //{errMsg: "getBluetoothAdapterState:ok", available: true, discovering: false} }, fail: function (res2) { // console.log('获取本机蓝牙适配器状态', res2) }, }) },
3.开始搜寻附近的蓝牙设备
//开始搜寻附近的蓝牙外围设备 startBluetoothDevicesDiscovery() { var that = this; // console.log('开始搜寻附近的蓝牙外围设备') wx.startBluetoothDevicesDiscovery({ powerLevel: "high", success: function (res) { console.log('开始搜寻附近的蓝牙外围设备', res) if (res.errCode == 0) { // 监听寻找到新设备的事件 that.onBluetoothDeviceFound() } }, fail: function (res) { console.log('开始搜寻附近的蓝牙外围设备', res) } }) },
4.监听寻找到新设备的事件
//监听寻找到新设备的事件 onBluetoothDeviceFound() { var that = this wx.onBluetoothDeviceFound((res) => { console.log(res); res.devices.forEach(device => { if (!device.name && !device.localName) { return } const foundDevices = this.data.devices const idx = that.inArray(foundDevices, 'deviceId', device.deviceId) console.log(idx); const data = {} if (idx === -1) { data[`devices[${foundDevices.length}]`] = device } else { data[`devices[${idx}]`] = device } this.setData(data) }) }) // 筛选数据自动连接对应设备 var deviceName = 'FT_' + this.data.bluetoothName; for (var i = 0; i < that.data.devices.length; i++) { if (that.data.devices[i].localName == deviceName) { //筛选完成,连接蓝牙 that.createBLEConnection(that.data.devices[i].deviceId) // console.log(that.data.devices[i]) this.setData({ newBluetoothData: [that.data.devices[i]], myDeviceId: [that.data.devices[i].deviceId], }) wx.showToast({ title: '匹配设备成功~', icon: 'success', duration: 2000 }) clearInterval(this.data.TimeFn) return } } },
5.连接蓝牙
createBLEConnection(deviceId) { var that = this // console.log('连接蓝牙', that.data.deviceId) for (var i = 0; i < that.data.devices.length; i++) { //连接蓝牙前先关闭已连接蓝牙 wx.createBLEConnection({ deviceId: deviceId, success: function (res) { // console.log('连接蓝牙成功', res) //获取连接设备的service服务 that.getBLEDeviceServices(deviceId); //停止搜寻附近的蓝牙外围设备 // wx.stopBluetoothDevicesDiscovery({ // success: function(res) { // console.log('停止搜寻附近的蓝牙外围设备',res) // }, // fail:function(res){ // } // }) }, fail: function (res) { console.log('连接蓝牙失败', res) }, }) },
getBLEDeviceServices(deviceId) { var that = this wx.getBLEDeviceServices({ deviceId: deviceId, success: function (res) { that.setData({ service: res.services }) console.log('获取连接设备的service服务', res) // that.getBLEDeviceCharacteristics(deviceId, res.services[0]['uuid']) for (let i = 0; i < res.services.length; i++) { if (res.services[i].isPrimary && res.services[i].uuid == '0000AA00-0000-1000-8000-00805F9B34FB') { that.setData({ myId: deviceId, serviceId: res.services[i].uuid }) //获取连接设备的所有特征值 that.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid) // return } } }, fail: function (res) { console.log('获取蓝牙失败', res) } }) },
getBLEDeviceCharacteristics(deviceId, serviceId) { var that = this wx.getBLEDeviceCharacteristics({ deviceId: deviceId, serviceId: serviceId, success: function (res) { console.log('获取连接设备的所有特征值', res); if (res.errCode == 0) { that.setData({ characteristicId: res.characteristics, // clickFlag: true, showModal: false, //loading关闭 wifiFlag: true // wifi弹窗开启 }) // that.onBLECharacteristicValueChange() for (var i = 0; i < res.characteristics.length; i++) { //启用低功耗蓝牙设备特征值变化时的 notify 功能 that.notifyBLECharacteristicValueChange(deviceId, serviceId, that.data.characteristicId[i]['uuid']) // 获取可以写入的设备的特征值uuid if (that.data.characteristicId[i]['properties']['write']) { that.setData({ uuId: that.data.characteristicId[i]['uuid'] }) } } } else { console.log('获取特征值失败') } }, }) },
notifyBLECharacteristicValueChange(deviceId, serviceId, characteristicId) { var that = this wx.notifyBLECharacteristicValueChange({ deviceId: deviceId, serviceId: serviceId, characteristicId: characteristicId, state: true, success: function (res) { console.log('启用低功耗蓝牙设备特征值变化时的 notify 功能', res) // console.log('启用低功耗蓝牙设备特征值变化时的 notify 功能', that.data.uuId) /*用来监听手机蓝牙设备的数据变化*/ that.onBLECharacteristicValueChange() }, fail: function (res) { console.log('启用低功耗蓝牙设备特征值变化时的 notify 功能失败', res) } }) },
onBLECharacteristicValueChange() {
var that = this
wx.onBLECharacteristicValueChange(function (res) {
console.log('监听低功耗蓝牙设备的特征值变化事件', res)
// console.log(`characteristic ${res.characteristicId} has changed, now is ${res.value}`)
// console.log(that.ab2hex(res.value))
// console.log(that.hexCharCodeToStr(that.ab2hex(res.value)))
var message = that.ab2hex(res.value)
that.readOrder(message)
})
},
// 连接wifi
wifiConnect() {
if (!this.data.wifiAccount || !this.data.wifiPassword) {
wx.showToast({
title: '不能为空',
icon: 'error',
duration: 2000
})
return false
}
// 处理要写入设备的值
this.getBluetoothValue()
},
11.获取要写入蓝牙设备的值
// 获取要写入蓝牙设备的值 getBluetoothValue() { // 1.0x50,2.wifi账号,3.0x8B,4.wifi密码,5.0xCF 6.服务器IP 端口号 子网信息 let that = this let { useValueOne, wifiAccount, useValueTwo, wifiPassword, useValueThree, serverIp, portNumber, subnetInfo } = that.data // 字符串转16进制 let a = that.strToHexCharCode(wifiAccount) // wifi账号 let b = that.strToHexCharCode(wifiPassword) // wifi密码 let c = that.strToHexCharCode(subnetInfo)// 服务器子网 //按硬件的需求 将3个定值 以及 wifi账号和密码拼成16进制字符串 let hesCaarCode = useValueOne + a + useValueTwo + b + useValueThree + serverIp + portNumber + c // 2个字符等于一个字节 往设备写入数据一次只能发一个包20个字节 var len = parseInt(hesCaarCode.length / 40) + 1 console.log(len); // 向设备写入数据 有几个包就发几次 for (var i = 0; i < len; i++) { // 截取每一个包的数据 var code = hesCaarCode.substr(i * 40, 40) that.writeBLECharacteristicValue(that.codebuffer(code)) } },
//发送数据 writeBLECharacteristicValue(value) { var that = this //连接蓝牙是记录session // console.log('写入设备', that.data.myId) // console.log('写入服务', that.data.serviceId) // console.log('写入特征值', that.data.uuId.toString()) console.log(value); wx.writeBLECharacteristicValue({ deviceId: that.data.myId, serviceId: that.data.serviceId, characteristicId: that.data.uuId.toString(), value: value, success: function (res) { if (res.errCode == 0) { that.setData({ wifiFlag: false, }) wx.showToast({ title: '连接成功', icon: 'success', duration: 2000 }) // // 暂时断开 // var closeTimeBlue = setInterval(() => { // that.closeBlueFn(); // wx.navigateBack({ // delta: 1, // }) // clearInterval(closeTimeBlue) // }, 5000); } else { wx.showToast({ title: '连接失败', icon: 'none', duration: 2000 }) } }, fail: function (err) { // console.log('写入数据返回值失败', err) }, }) },
到这里我这个蓝牙配网功能就初步完成了,后续会和硬件对接,有问题会及时更新,然后在附上几个小方法
//字符串转16进制 strToHexCharCode(str) { if (str === "") return ""; var hexCharCode = []; // hexCharCode.push("0x"); for (var i = 0; i < str.length; i++) { hexCharCode.push((str.charCodeAt(i)).toString(16)); } return hexCharCode.join(""); }, //将16进制转ArrayBuffer codebuffer: function (val) { // 将16进制转化为ArrayBuffer return new Uint8Array(val.match(/[\da-f]{2}/gi).map(function (h) { return parseInt(h, 16) })).buffer }, //16进制转字符串 hexCharCodeToStr(hexCharCodeStr) { var trimedStr = hexCharCodeStr.trim(); var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr; var len = rawStr.length; if (len % 2 !== 0) { alert("Illegal Format ASCII Code!"); return ""; } var curCharCode; var resultStr = []; for (var i = 0; i < len; i = i + 2) { curCharCode = parseInt(rawStr.substr(i, 2), 16); // ASCII Code Value resultStr.push(String.fromCharCode(curCharCode)); } return resultStr.join(""); },
为什么我上面往设备发送数据的时候要分包
BLE 4.0 中发送一个数据包只能包含 20 字节的数据,大于 20 字节只能分包发送。微信小程序提供的 API 中似乎没有自动分包的功能,这就只能自己手动分包了。调试中发现,在 iOS 系统中调用 wx.writeBLECharacteristicValue 发送数据包,回调 success 后紧接着发送下一个数据包,很少出现问题,可以很快全部发送完毕。而安卓系统中,发送一个数据包成功后紧接着发送下一个,很大概率会出现发送失败的情况,在中间稍做延时再发送下一个就可以解决这个问题(不同安卓手机的时间长短也不一致),照顾下一些比较奇葩的手机,大概需要延时 250 ms 。不太好的但是比较科学的办法是,只要成功发送一个数据包则发送下一个,否则不断重发,具体就是
wx.writeBLECharacteristicValue 回调 fail 则重新发送,直至发送完毕
下面这个链接是我一个前辈的博客,对我这个功能的开发帮组非常大,比我的更完善
https://www.cnblogs.com/guhonghao/p/9947144.html
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。