微信小程序> 微信小程序蓝牙BLE开发实战API及流程介绍一-微信小程序ble-微信小程序ibeacon

微信小程序蓝牙BLE开发实战API及流程介绍一-微信小程序ble-微信小程序ibeacon

浏览量:3990 时间: 来源:Smile_ping
微信小程序蓝牙BLE实战开发(一)迟来的更新。从4月份以来项目中断续在对接好几个共享产品,关于蓝牙BLE设备,通过蓝牙与设备之间通信进行使用产品。开发中也遇到不少问题哈,后面抽时间续篇。写得不好,请各位大神多多指教。1.

此篇主要介绍一些API操作及一些返回数据结构,项目已上线。后面抽时间上demops:如果有了解过蓝牙这块,代码可直接复制使用

文章目录微信小程序蓝牙BLE实战开发(一)关于字节流程图使用步骤初始化数据给变量赋值1.`初始化蓝牙`模块2.`监听寻找新设备`事件设备返回数据`效果图`注意:说明:3.`开始`搜寻附近的蓝牙设备4.`停止`搜寻附近的蓝牙设备5.`连接`低功耗蓝牙设备6.获取蓝牙`所有服务`设备返回数据`效果图`7.获取某个服务中所有特征值返回数据结构`效果图`注意:8.写入数据9.断开蓝牙设备的连接10.错误码判断处理数据方法关于下篇内容关于字节2.

字节(Byte):是计算机信息技术用于计量存储容量的一种计量单位,作为一个单位来处理的一个二进制数字串。

3.

其中下发指令或处理数据时都可以应用到

1B(byte,字节)8bit(比特),相当于一个字符一个字节能表示的最大的整数就是255例如:数据为5d000001be5d理解为6个字节(6B)流程图4.

BLE执行大致流程,为了节省空间,画的比较乱哈。

使用步骤5.

微信小程序低功耗蓝牙API

6.

微信小程序官方_蓝牙说明

这里单独放在一个js文件中初始化数据7.

根据需求定义,个人在一个项目中开发好几个产品,同时对接不同蓝牙协议供应商,有些变量放全局,根据不同供应商来操作

varserviceUUID[]//主service的uuid列表varwriteUUID"";//写读UUIDvarnotifyUUID"";//notifyUUIDvarfilterServiceUUID"";//过滤获取到的服务uuid(有些会返回多条数据)varfilterDeviceName"";//设备名称varmacAddress"";//保存得到mac地址varflagFromTypes'';//来源类型var_discoveryStartedfalse;vardeviceId'';//用于区分设备的idvar_deviceId'';var_serviceId'';var_characteristicId'';varstatusfalse;//当前状态varaction_type'';//操作类型varcode-1;varisnotExisttrue给变量赋值8.

设备相关服务通常蓝牙协议文档上有说明,Read、Write、Notify。如果没有说明可通过搜索设备看到

9.

某些供应商读写通过统一用一个服务的

serviceUUID[0]"0000*E0-00*0-*0*0-*0*0-00**5F9**4*B";//主service的uuid列表writeUUID"00*0**E2-00*0-*0*0-*0*0-00**5F9**4*B";//写读UUIDnotifyUUID"00*0**E1-00*0-*0*0-*0*0-00**5F9**4*B";//notifyUUIDfilterServiceUUID"*E0";filterDeviceNamegetNameMac(macAddress,6,'abc_');//设备名称1.初始化蓝牙模块10.

wx.openBluetoothAdapter(Objectobj)ps:调用此方法initBle()就可以使用哦,【建议顺序查看,易理解】

functioninitBle(fromMac,flagTypes,currentSerial){//断开连接【每次初始化先断开连接】closeBLEConnection();//macAddressclearSymbol(fromMac);macAddressfromMac;//保存macflagFromTypesflagTypes//类型来源currentSerialValcurrentSerial//当前操作序号wx.openBluetoothAdapter({success:(res){console.log('openBluetoothAdapter初始化蓝牙模块是否成功:',res)//监听寻找新设备事件onBluetoothDeviceFound();//开始搜寻附近的蓝牙外围设备startBluetoothDevicesDiscovery();},fail:(res){console.log('初始化蓝牙失败',res);//自行处理【可弹窗提示用户开启蓝牙】,这通过回调处理asddErrorCallback(res.errCode,"");//监听蓝牙适配器状态变化事件【根据需求是否执行】//wx.onBluetoothAdapterStateChange(function(res){//console.log('蓝牙适配器状态更改结果:',res)//if(res.available){//console.log('蓝牙可用,搜索设备:--》')//onBluetoothDeviceFound();//startBluetoothDevicesDiscovery();//}//})}})}2.监听寻找新设备事件11.

wx.onBluetoothDeviceFound(functioncallback)

12.

说明:广播数据:可以得到当前蓝牙设备的相关数据,另外,如果设备有返回其他数据时在advertisData数据段中得到,【有些供应商是没有返回的】

设备返回数据效果图13.

下图是两家供应商设备返回的数据,左图advertisData返回8个字节数据【数据需转换】。右图则没有。同时可以看到返回name格式也是不一样的【自定义】

注意:安卓下部分机型需要有位置权限才能搜索到设备,需留意是否开启了位置权限Android设备返回是mac地址,IOS返回是uuid,由32位字母和数据组成,并且是动态的。说明:14.

为了保证准确性建议通过mac地址匹配。mac地址正常是12位

15.

假设:advertisData字段返回数据是0000365544332211。【可根据文档说明取需要数据】

在advertisData得到数据(不一定有数据哦),截取mac地址匹配。【假如第4位至16位为mac(365544332211)】,用变量保存下来。16.

如果advertisData没有返回其他数据,该如何匹配设备?

通过设备name进行匹配设备,供应商通常会以前缀+mac前/后几位,或12位。当前还有一些只有前缀的比如FIC_992f3e,其中992f3e是设备6位mac地址。【根据实际情况操作】17.

案例:

以下demo提供两种匹配设备方式.通过mac或name匹配设备【每个供应商返回的name格式不一样】/***监听寻找新设备事件*搜索匹配设备后,自动连接设备*/functiononBluetoothDeviceFound(){wx.onBluetoothDeviceFound((res){console.log('广播数据结果:',res);res.devices.forEach(device{if(!device.name!device.localName){return}//转换后,得出相关数据varhexStrab2hex(device.advertisData);console.log("广播数据中转换后:advertisData----"+hexStr);//通过获取mac匹配if((macAddress!"")(macAddressdevice.deviceId)isnotExist){isnotExistfalse;deviceIddevice.deviceId;console.log('android--tempDeviceId:'+deviceId);//停止搜寻附近的蓝牙外围设备stopBluetoothDevicesDiscovery();//连接设备createBLEConnection();}//通过name匹配设备letdeviceNamedevice.name.toUpperCase();if((deviceName.indexOf(filterDeviceName)!-1)isnotExist){isnotExistfalse;deviceIddevice.deviceId;console.log('iosorandroid--tempDeviceId:'+deviceId);//停止搜寻附近的蓝牙外围设备。stopBluetoothDevicesDiscovery();//连接设备createBLEConnection();}})})}3.开始搜寻附近的蓝牙设备18.

wx.startBluetoothDevicesDiscovery(Objectobject)

19.

注意此操作比较耗费系统资源,请在搜索并连接到设备后调用wx.stopBluetoothDevicesDiscovery方法停止搜索

functionstartBluetoothDevicesDiscovery(){console.log("执行连接蓝牙设备回调空"+_discoveryStarted);if(_discoveryStarted){return;}_discoveryStartedtruewx.startBluetoothDevicesDiscovery({services:serviceUUID,//如果设置此参数,则只搜索广播包有对应uuid的主服务的蓝牙设备。allowDuplicatesKey:false,success:(res){console.log('启动搜索蓝牙设备,结果:',res)//onBluetoothDeviceFound()//先调用此方法再使startBluetoothDevicesDiscovery},fail(res){asddErrorCallback(res.errCode,"");console.log('startBluetoothDevicesDiscoveryfail',res);}})}4.停止搜寻附近的蓝牙设备20.

wx.stopBluetoothDevicesDiscovery(Objectobject)

//停止搜寻附近的蓝牙外围设备。functionstopBluetoothDevicesDiscovery(){wx.stopBluetoothDevicesDiscovery()}5.连接低功耗蓝牙设备21.

wx.createBLEConnection(Objectobject)

/***连接蓝牙设备*/functioncreateBLEConnection(){varthatthis;wx.createBLEConnection({deviceId:deviceId,success:(res){wx.showToast({title:'设备连接成功',duration:2000})getBLEDeviceServices(deviceId)},fail:(res){console.log('createBLEConnectionfail',res);asddErrorCallback(res.errCode,"");}})//停止搜索stopBluetoothDevicesDiscovery();}6.获取蓝牙所有服务22.

wx.onBLEConnectionStateChange(functioncallback)

23.

wx.getBLEDeviceServices(Objectobject)

24.

注意:有些供应商会返回多个服务,只要找自己需要的服务就好

25.

监听蓝牙连接状态,可以处理连接连接意外断开等情况

26.

获取需要的蓝牙服务后,再调用获取蓝牙特征值方法

设备返回数据效果图27.

假设:需要的服务是包含EE0的,只需要过滤下就可以【这里通过indexOf】

functiongetBLEDeviceServices(deviceId){//监听低功耗蓝牙连接状态的改变事件wx.onBLEConnectionStateChange(function(res){console.log("onBLEConnectionStateChange:",res);//该方法回调中可以用于处理连接意外断开等异常情况console.log(`device${res.deviceId}statehaschanged,connected:${res.connected}`)if(res.connectedfalse){console.log("连接意外断开等****",_deviceId);_deviceId'';if(flagFromTypes1flagFromTypes2){asddErrorCallback(1010,"");}}});//获取蓝牙所有servicewx.getBLEDeviceServices({deviceId:deviceId,success:(res){//console.log("获取蓝牙设备所有服务(service)",res);for(leti0;ires.services.length;i++){lettmpUuidres.services[i].uuid;if((res.services[i].isPrimary)(tmpUuid.indexOf(filterServiceUUID)!-1)){//获取蓝牙特征值getBLEDeviceCharacteristics(deviceId,res.services[i].uuid)return}}},fail:(res){console.log('getBLEDeviceServicesfail',res);asddErrorCallback(res.errCode,"");}})}7.获取某个服务中所有特征值28.

wx.getBLEDeviceCharacteristics(Objectobject)

29.

wx.onBLECharacteristicValueChange(functioncallback)

30.

注意:返回数据中的properties的结构,里面返回该服务下的特征值是否支持read、write、notify、indicate操作。

返回数据结构效果图注意:31.

根据文档协议读、写、通知服务【前面定义的变量】,遍历对象来获取想要的特征值uuid处理相关逻辑

32.

启用低功耗蓝牙设备特征值变化时的notify功能,注意:必须设备的特征值支持notify或者indicate才可以成功调用。

33.

监听低功耗蓝牙设备的特征值变化事件。注意:必须先启用notifyBLECharacteristicValueChange接口才能接收到设备推送的notification。

34.

监听onBLECharacteristicValueChange,第一时间获取设备返回的数据

35.

如果需要找到设备后,先获取一些设备信息操作,可以在write中发送相关指令

/***获取蓝牙特征值*/functiongetBLEDeviceCharacteristics(deviceId,serviceId){console.log("设备:"+deviceId+'******************服务:'+serviceId);wx.getBLEDeviceCharacteristics({deviceId:deviceId,serviceId:serviceId,success:(res){//console.log('蓝牙设备特征值信息:',res);console.log('getBLEDeviceCharacteristicssuccess',res.characteristics)for(leti0;ires.characteristics.length;i++){letitemres.characteristics[i]varitemUUIDitem.uuid.toUpperCase();//转大写//read操作if(item.properties.readitemUUIDwriteUUID){wx.readBLECharacteristicValue({deviceId:deviceId,serviceId:serviceId,characteristicId:item.uuid,})}//write操作if(item.properties.writeitemUUIDwriteUUID){console.log("写特征值-----------------------"+item.uuid);_deviceIddeviceId_serviceIdserviceId_characteristicIditem.uuid//发送信息查询指令【根据需求】if(flagFromTypes1||flagFromTypes2){//血压、秤handleTimeToHex();}}//notify操作,注意调用监听特征值变化if(notifyUUIDitemUUID){if(item.properties.notify||item.properties.indicate){console.log('调用notifyBLECharacteristicValueChange前',item.uuid);wx.notifyBLECharacteristicValueChange({deviceId:deviceId,serviceId:serviceId,characteristicId:item.uuid,state:true,success(res){console.log('notification通知数据',res);statustrue;//wx.hideLoading();},fail(res){console.log('notifyBLECharacteristicValueChangefali',res);}})}}}},fail:(res){console.log('getBLEDeviceCharacteristicsfail',res)asddErrorCallback(res.errCode,"");}})//操作之前先监听,保证第一时间获取数据wx.onBLECharacteristicValueChange(function(res){console.log(`characteristic${res.characteristicId}haschanged,nowis${res.value}`)console.log("操作类型:"+action_type);varresDataab2hex(res.value);//转16进制console.log("设备返回数据---",resData);//5d0000000001be304d//判断不同类型处理数据if(flagFromTypes1){console.log('开始调用血压计》处理返回的数据');bloodPressureObj.filterStr(resData);}})}8.写入数据36.

wx.writeBLECharacteristicValue(Objectobject)

37.

注意:这里我用1秒延迟,如果马上发送数据,易出现发送失败问题

接收hex参数【下发指令数据】,向设备写入二进制数据。注意:注意:必须设备的特征值支持write才可以成功调用。/***写入数据*/functionwriteData(hex,action''){if(!status){return;}if(!_deviceId){asddWriteErrors('w');return;}setTimeout((){//类型转换varenDataBufnewUint8Array(hex);varbuffer1enDataBuf.bufferconsole.log("发送内容长度:",buffer1.byteLength)console.log('写入的数据:'+_deviceId+'服务serviceId---》'+_serviceId+'特征characteristicId---》'+_characteristicId);wx.writeBLECharacteristicValue({deviceId:_deviceId,serviceId:_serviceId,characteristicId:_characteristicId,value:buffer1,success:(res){wx.hideLoading();console.log("写数据返回结果",res.errMsg);//项目需求:发送某个指令后的需要处理回调if(action'lastZero'){console.log('最后一次写入00需执行回调》');//回调目的:执行调用提交接口eyeCareObj.eyeCareCallback();}},fail(res){console.log("写数据失败..",res);asddErrorCallback(res.errCode,"");}})},1000)}9.断开蓝牙设备的连接38.

wx.closeBLEConnectionwx.closeBluetoothAdapter

39.

注意:断开蓝牙设备连接同时还要关闭蓝牙模块,否则安卓设备下再次无法搜索到设备

/***断开蓝牙连接*/functioncloseBLEConnection(){//停止搜索stopBluetoothDevicesDiscovery();console.log("断开与低功耗蓝牙设备的连接。",deviceId);if(deviceId){wx.closeBLEConnection({deviceId:deviceId,success:function(res){console.log("closeBLEConnection。success",res);},fail:function(res){console.log("closeBLEConnection。fail",res);},complete:function(){statusfalse;}})//关闭蓝牙模块wx.closeBluetoothAdapter({success:function(res){console.log("closeBluetoothAdapterres:",res);},fail:function(error){console.log("closeBluetoothAdaptererror:",error);}})}_discoveryStartedfalse;isnotExisttrue;_deviceId'';deviceId'';}10.错误码判断40.

10006错误码我单独处理,自动重连操作

functionbluetoothStatus(errorType){switch(errorType){case10001:wx.showModal({title:'提示',content:'请检查手机蓝牙是否打开',showCancel:false})break;case10002:wx.showToast({title:'没有找到指定设备',icon:'none'})break;case10003:wx.showToast({title:'连接失败',icon:'none'})closeBLEConnection();break;case10004:wx.showToast({title:'没有找到指定服务',icon:'none'})closeBLEConnection();break;case10005:wx.showToast({title:'没有找到指定特征值',icon:'none'})closeBLEConnection();break;case10007:case10008:case10013:wx.showToast({title:'设备启动失败,请重试',icon:'none'})break;case10009:wx.showModal({title:'提示',content:'当前系统版本过低,请更新版本体验',showCancel:false})break;case10012:wx.showToast({title:'连接超时',icon:'none'})break;}}处理数据方法/***匹配规则:取名称后面的mac地址*mac地址:假设C7:E2:90:17:1A:40*len:截取长度为*/functiongetNameMac(macAddress,len,name){letclearColonMacclearSymbol(macAddress);letlastFourMacclearColonMac.substring(clearColonMac.length-len);letstrNamename.toUpperCase();strNamestrName+lastFourMac.toUpperCase();//转大写console.log('拼接后的'+strName);//abc_171A40returnstrName}/***去掉冒号*/functionclearSymbol(str){strstr.replace(/:/g,"");//取消字符串中出现的所有冒号returnstr;}/***rrayBuffer转16进度字符串*/functionab2hex(buffer){varhexArrArray.prototype.map.call(newUint8Array(buffer),function(bit){return('00'+bit.toString(16)).slice(-2)})returnhexArr.join('');}关于下篇内容41.

在实际中使用的案例。

版权声明

即速应用倡导尊重与保护知识产权。如发现本站文章存在版权问题,烦请提供版权疑问、身份证明、版权证明、联系方式等发邮件至197452366@qq.com ,我们将及时处理。本站文章仅作分享交流用途,作者观点不等同于即速应用观点。用户与作者的任何交易与本站无关,请知悉。

  • 头条
  • 搜狐
  • 微博
  • 百家
  • 一点资讯
  • 知乎