当前位置: 首页 > Web前端 > HTML

快来解锁小程序蓝牙开发技能

时间:2023-03-28 00:33:09 HTML

快来解锁小程序的蓝牙开发技巧吧没有认真开发过。这次是因为接到一个外包项目,记录一下开发过程和遇到的问题。实际项目的效果很简单。有两个页面,一个页面建立连接,另一个页面显示数据,大致如下图所示。老板说,这个简易版只有2页,1000元。想了想,这好像也没什么问题,说不定一天就搞定了,暗暗高兴。但实际情况远远超过了预算的开发时间。现在项目已经发布上??线,回过头来算了一下断断续续的开发时间差不多要2天。这个算计着实是不痛快,不过应该用来加深体会吧。下面记录实际遇到的问题,开发框架:uniapp,蓝牙调用与微??信小程序中基本一致。Establishingaconnection建立连接基本就是这一步:初始化蓝牙,开始搜索附近设备在搜索附近设备回调中找到要连接的设备连接设备停止搜索附近设备重新连接,所以需要断开已有连接初始化前,可以调用蓝牙模块断开连接,否则搜索不到要连接的设备。//关闭蓝牙模块uni.closeBluetoothAdapter({success(res){//初始化蓝牙uni.openBluetoothAdapter({success(res){console.log('初始化蓝牙成功')},fail(err){console.log('初始化蓝牙失败')}})}})开始搜索附近设备,在搜索附近设备的回调中找到要连接的设备。搜索回调中会包含蓝牙的名称和设备ID,通过名称可以识别要连接的名称对于蓝牙,设备ID用于连接蓝牙。该方法消耗系统资源。如果连接成功,需要主动调用关闭蓝牙搜索。//开始搜索附近的设备uni.startBluetoothDevicesDiscovery({success(){//打开监听回调uni.onBluetoothDeviceFound(found)}})functionfound(res){if(res.devices[0]&&res.devices[0].name.includes('XXX')){//连接设备uni.createBLEConnection({deviceId:res.devices[0].deviceId,success(res){//停止搜索uni.stopBluetoothDevicesDiscovery()}})}}成功建立与监控消息的连接。由于这次连接的是BluetoothLowEnergy,所以后续需要监控数据返回和数据写入。最后,需要调用notifyBLECharacteristicValueChange,开启低功耗蓝牙设备特征值变化时的notify功能。该方法还需要两个参数,蓝牙特性的UUID(characteristicId)和蓝牙特性对应的服务的UUID(serviceId)。获取蓝牙feature对应的service的UUID(serviceId):uni.getBLEDeviceServices({deviceId,success(res){//serviceId},})根据获取到的serviceId继续获取characteristicId,这里需要注意就是返回的characteristicId在一个数组里面,里面有对应读写函数的描述,会根据读写的实际情况使用不同的值。如果您不确定,请咨询硬件开发商。uni.getBLEDeviceCharacteristics({deviceId,serviceId,success(res){//characteristicId}})最后开启消息监听,开启蓝牙低功耗设备特征值变化时的notify功能,订阅该特征。另外,在监听devicecharacteristicValueChange事件之前必须开启notifyBLECharacteristicValueChange。uni.notifyBLECharacteristicValueChange({state:true,deviceId,//设备idserviceId,//监听指定服务characteristicId,//监听对应的特征值success(res){//监听消息变化}})监听消息变化而返回的res.value就是要使用的值,但是这个值的格式是ArrayBuffer,需要进一步转换使用。uni.onBLECharacteristicValueChange(res=>{ab2hex(res.value)})//ArrayBuffer到十六进制字符串ab2hex(buffer){consthexArr=Array.prototype.map.call(newUint8Array(buffer),function(bit){return('00'+bit.toString(16)).slice(-2)})returnhexArr.join('')}这里写入了数据,我们可以取回数据,但是正常运行还有数据的写入,通过编写不同的指令来执行相关的功能操作或获取不同的数据。这里同样需要注意的是,写入的数据也是ArrayBuffer格式,写入前需要注意转换。consttypedArray=newUint8Array(hexStr.match(/[\da-f]{2}/gi).map(function(h){returnparseInt(h,16)}))constbuf=typedArray.bufferuni.writeBLECharacteristicValue({deviceId,serviceId,characteristicId,value:buf,success(){console.log('writeBLECharacteristicValuesuccess')}})另外需要注意的是,写入数据时返回的数据不会在回调中返回当前的方法。还是在上面的onBLECharacteristicValueChange特征值变化事件中,通过具体的返回字符来区分当前的操作行为。下面的后记是一些踩坑的记录。如果没有那么多坑,也不会浪费那么多时间。如果你也是第一次接手这类项目,希望对你有所帮助。数据格式前端与蓝牙协议的通信方式不再与平时后端调用接口相同。和硬件同事沟通的时候,一定要沟通清楚。首先传输的数据不是string也不是json,而是ArrayBuffer,然后是传输对应的字符内容。这个通信的格式是十六进制,长度是16位,但是在JS中,实际发送的是32个字符的长度。字符串必须在使用前转换为ArrayBuffer。比如接口文档中的命令是0x04,但是实例需要发送的是A1A10400000000000000000000000000。如果您不确定这种情况,您应该积极与您的硬件同事沟通。数据转换文档中用到的一些数据的转换表示如下:data1=data[9]*256+data[10]一开始没看懂,以为有什么特殊的逻辑,后来发现意识到它从十六进制转换为10进制。但是有一种更简单的方法可以在JS中转换它。注:这里取的下标对应两个字符。例如:16进制字符0x1234按照上面的转换就是parseInt('12',16)*256+parseInt('34',16)等于4660,JS直接用parseInt转换成parseInt('0x1234')或者parseInt('1234',16),0x开头的字符,parseInt默认以16进制解析,最终结果为4660。这里还有一个高低位转换的问题。我这里遇到的是高位在前,低位在后。暂时不需要额外处理。实际开发中是否需要转换,需要双方沟通。数据使用本次使用的数据为上述数据转换中引用的格式。其实一个完整的数据就是由两个下标值组成,再转换成16进制字符就是4位字符。所以每次转换都需要一组4个字符,因为涉及到多个数据值,需要排除前后有无效数据。最终代码如下所示:constoData=ab2hex(res.value).slice(2).replace(/(.{4})/g,'$1,').split(',')for(vari=3;i