当前位置:   article > 正文

微信小程序实现蓝牙连接通讯

微信小程序实现蓝牙连接通讯

由于最近的项目在做小程序蓝牙通讯这块的内容,所以将实现的过程在这简单的记录下。

1、首先要初始化蓝牙-检查蓝牙适配器是否打开

  1. async initBluetooth(): Promise<void> {
  2. return new Promise((resolve: any, reject: any) => {
  3. const _this = this
  4. if (BluetoothController.adapterOpend) {
  5. console.log("蓝牙适配器已打开")
  6. resolve(true)
  7. return
  8. }
  9. wx.openBluetoothAdapter({
  10. success(res) {
  11. BluetoothController.adapterOpend = true
  12. console.log("=====*****蓝牙适配器已打开")
  13. resolve(true)
  14. },
  15. fail(error) { //用来判断蓝牙是否已打开
  16. reject(error)
  17. BluetoothController.adapterOpend = false
  18. console.log("=====*****蓝牙适初始化失败", error)
  19. }
  20. })
  21. })
  22. }
  23. //使用案例
  24. initBluetooth().then()

2、开始搜寻附近的蓝牙外围设备

  1. /**
  2. * @param options
  3. * options.keywords 蓝牙名称筛选关键字
  4. * options.deviceid 可选参数,蓝牙设备id,连接用
  5. */
  6. async searchAroundBLE(options: any): Promise<void> {
  7. return new Promise((resolve: any, reject: any) => {
  8. const _this = this
  9. if (_this.startDiscovery) {
  10. console.log("已开启蓝牙扫描,勿重复开启")
  11. resolve(true)
  12. return
  13. }
  14. _this.startDiscovery = true
  15. wx.startBluetoothDevicesDiscovery({
  16. allowDuplicatesKey: true,
  17. services: options.services,
  18. success(res) {
  19. console.log('搜索成功', res);
  20. resolve(true)
  21. },
  22. fail(error) {
  23. reject(error)
  24. _this.startDiscovery = false
  25. },
  26. })
  27. })
  28. }
  29. //使用案例
  30. searchAroundBLE({ 'keywords': [''], services: [] }).then()

3、监听搜索到的设备

  1. /**
  2. * @param options
  3. * options.keywords 蓝牙名称筛选关键字
  4. * options.deviceid 可选参数,蓝牙设备id,连接用
  5. */
  6. async onBluetoothDeviceFound(options: any): Promise<void> {
  7. return new Promise((resolve: any, reject: any) => {
  8. let _this = this
  9. let { keywords } = options
  10. // 超时自动结束
  11. _this.findTimer = setTimeout(() => {
  12. clearTimeout(_this.findTimer)
  13. if (!_this.connectStatus) {
  14. reject({
  15. success: false
  16. })
  17. console.log('蓝牙扫描超时,自动关闭任务')
  18. }
  19. }, 3000); //时间根据自己的需求定
  20. let arr: any = []
  21. wx.onBluetoothDeviceFound(res => {
  22. let devices = res.devices;
  23. devices.forEach((device) => {
  24. if (!device.name && !device.localName) {
  25. return
  26. }
  27. // 获取设备MAC地址,并根据关键字过滤
  28. let systemInfo = wx.getSystemInfoSync()
  29. let iosDevice = systemInfo.system.toLowerCase().indexOf("ios") > -1;
  30. let deviceMac = iosDevice ? uuid2Mac(device.advertisData) : device.deviceId
  31. // keywords
  32. if (keywords && keywords.length > 0) {
  33. let key = keywords[0]
  34. if (device.name.indexOf(key) >= 0) {
  35. arr.push({
  36. ...device,
  37. deviceMac
  38. })
  39. }
  40. if (arr.length) {
  41. let foundDevices = arr
  42. _this.deviceList = foundDevices
  43. resolve({
  44. data: arr,
  45. success: true
  46. })
  47. }
  48. }
  49. })
  50. })
  51. })
  52. }
  53. /**
  54. * 统一安卓与IOS端deviceId展示
  55. * @param advertisData
  56. * 在安卓设备中,获取到的 deviceId 为设备 MAC 地址,iOS 上则为设备 uuid,
  57. * 因此为了展示一致需要将ios的展示进行输入(当然IOS的连接还是得用获取到的uuid)
  58. */
  59. function uuid2Mac(advertisData: any) {
  60. if (advertisData) {
  61. let mac = Array.prototype.map
  62. .call(new Uint8Array(bf), (x) => ("00" + x.toString(16)).slice(-2))
  63. .join(":");
  64. mac = mac.toUpperCase();
  65. return mac;
  66. }
  67. }
  68. 使用案例: onBluetoothDeviceFound({ 'keywords': [''] }).then() //keywords根据自己的需求去定,

4、处理蓝牙连接(搜索到设备开始蓝牙链接)

  1. /**
  2. * @param {string} options.deviceId 蓝牙设备id,连接用
  3. */
  4. async createBLEConnection(options: any): Promise<void> {
  5. return new Promise((resolve: any, reject: any) => {
  6. let { deviceId } = options,_this = this
  7. _this.deviceId = deviceId
  8. if (_this.connectStatus) {
  9. wx.closeBLEConnection({
  10. deviceId
  11. })
  12. }
  13. let timeout = 3000 //根据自己需求去定
  14. console.log('开始连接蓝牙--', deviceId)
  15. _this.stopBLEDevicesTask()
  16. wx.createBLEConnection({
  17. deviceId,
  18. timeout,
  19. success(res) {
  20. console.log('蓝牙连接成功-----', deviceId)
  21. _this.connectStatus = true
  22. resolve(true)
  23. },
  24. fail() {
  25. _this.connectStatus = false
  26. reject(false)
  27. }
  28. })
  29. })
  30. }
  31. 使用案例: createBLEConnection({ deviceId: tmp[0].deviceId }).then()

5、连接成功后,要获取蓝牙的所有服务 进而根据项目需求的服务 去获取对应的特征 来进行读写操作

  1. /**
  2. * @param deviceId 蓝牙设备Id,来自createBLEConnection调用
  3. */
  4. async getBLEDeviceServices(deviceId: any): Promise<void> {
  5. return new Promise((resolve: any, reject: any) => {
  6. let _this = this
  7. wx.getBLEDeviceServices({
  8. deviceId,
  9. success(res) {
  10. /**
  11. * 16 位 UUID 从对接文档中获取(注意都是0000开头,接着的4位数字为16进制的uuid,所有服务只有4位uuid不一样)
  12. 注意有多个服务,不同服务的操作不一样,单个服务只能执行单个操作,所以这里需要建立多个连接
  13. */
  14. for (let i = 0; i < res.services.length; i++) {
  15. // 注意uuid的大小写
  16. if (
  17. res.services[i].isPrimary &&
  18. res.services[i].uuid == "0000D0FF-0000-1000-8000-008cbhschs" //设备id,根据自己的项目去走
  19. ) {
  20. // _this.getBLEDeviceCharacteristics(res.services[i].uuid);
  21. resolve({
  22. data: res.services[i].uuid,
  23. sucess: true
  24. })
  25. return;
  26. }
  27. }
  28. },
  29. fail: (res) => {
  30. reject({
  31. sucess: false,
  32. data: res.errMsg
  33. })
  34. console.log("服务获取失败------------->", res.errMsg);
  35. },
  36. });
  37. })
  38. }
  39. async getBLEDeviceCharacteristics(serviceId: any): Promise<void> {
  40. return new Promise((resolve: any, reject: any) => {
  41. let _this = this
  42. wx.getBLEDeviceCharacteristics({
  43. deviceId: _this.deviceId, //设备id根据自己项目的去赋值
  44. serviceId, //服务id
  45. success: (res) => {
  46. // 设备特征列表
  47. let characteristics = res.characteristics;
  48. for (let i = 0; i < characteristics.length; i++) {
  49. let item = characteristics[i];
  50. if (item.properties.write) {
  51. this.serviceId = serviceId
  52. this.characteristicId = item.uuid
  53. }
  54. if (item.properties.read) {
  55. wx.readBLECharacteristicValue({
  56. deviceId: _this.deviceId,
  57. serviceId,
  58. characteristicId: item.uuid
  59. });
  60. }
  61. if (item.properties.write) {
  62. // resolve({
  63. // data: 1,
  64. // sucess: true
  65. // })
  66. }
  67. if (item.properties.notify || item.properties.indicate) {
  68. /* 启用蓝牙低功耗设备特征值变化时的 notify 功能,订阅特征。注 意:必须设备的特征支持 notify 或者 indicate 才可以成功调用。
  69. 另外,必须先启用 wx.notifyBLECharacteristicValueChange 才能监听到设备 characteristicValueChange 事件*/
  70. wx.notifyBLECharacteristicValueChange({
  71. deviceId: _this.deviceId,
  72. serviceId,
  73. characteristicId: item.uuid,
  74. state: true,
  75. });
  76. resolve({
  77. data: item.properties,
  78. sucess: true
  79. })
  80. }
  81. }
  82. },
  83. fail(error: any) {
  84. reject({
  85. sucess: false,
  86. data: error
  87. })
  88. }
  89. });
  90. })
  91. }
  92. 使用案例: let { data } = await getBLEDeviceServices(tmp[0].deviceId) //data就是所有服务内容
  93. if (data) {
  94. // 2、获取蓝牙低功耗设备某个服务中所有特征 (characteristic)
  95. let ble_chart = await getBLEDeviceCharacteristics(data)
  96. if (ble_chart.sucess) {
  97. let item = ble_chart.data
  98. // 该特征是否支持 write 操作
  99. if (item.write) {
  100. // resolve(true)
  101. this.handleWriteSucess(); //处理写操作
  102. }
  103. // 该特征是否支持 notify ,indicate操作 ,开启监听订阅特征消息
  104. if (item.notify || item.indicate) {
  105. this.watchBleData()//监听蓝牙数据
  106. }
  107. }
  108. }

6、读写成功后开始根据蓝牙协议进行操作(蓝牙协议有设备方提供)

  1. handleWriteSucess() //写成功后的操作
  2. watchBleData() {
  3. wx.onBLECharacteristicValueChange(async (res) => { //监听蓝牙数据变化
  4. let resHex = ab2hex(res.value).toLocaleUpperCase() //包数据, 根据蓝牙协议去进行处理
  5. let { data } = writeBLECharacteristicValue('对应指令', '脚电极')
  6. })
  7. }
  8. /**
  9. * ArrayBuffer转16进度字符串
  10. * @param buffer
  11. */
  12. // ArrayBuffer转16进度字符串
  13. ab2hex(buffer: any) {
  14. var hexArr = Array.prototype.map.call(new Uint8Array(buffer), function (bit) {
  15. return ("00" + bit.toString(16)).slice(-2);
  16. });
  17. return hexArr.join("");
  18. }

 7、处理蓝牙写指令

  1. /**
  2. * 4. 发送蓝牙指令。蓝牙指令超出20字符时需要截断多次发送
  3. * @param {string} cmdStr 蓝牙指令
  4. * @param {string} cmdName 蓝牙指令名称——可选用于打印调试
  5. */
  6. async writeBLECharacteristicValue(cmdStr: any, cmdName: string): Promise<void> {
  7. // // console.log("发送蓝牙指令------------》", cmdStr, cmdName);
  8. return new Promise((resolve: any, reject: any) => {
  9. let _this = this
  10. let data = cmdStr.split(',')
  11. let buffer = new ArrayBuffer(data.length);
  12. let dataViewLast = new DataView(buffer);
  13. for (let i = 0; i < data.length; i++) {
  14. dataViewLast.setUint8(i, data[i]);
  15. }
  16. let param: any = {
  17. deviceId: _this.deviceId,
  18. serviceId: _this.serviceId,
  19. characteristicId: _this.characteristicId, //在获取特性那有
  20. value: dataViewLast.buffer,
  21. };
  22. console.log("param", param)
  23. wx.writeBLECharacteristicValue({
  24. ...param,
  25. success: function () {
  26. console.log("发送指令成功", cmdName);
  27. resolve({
  28. data: {
  29. cmdName,
  30. sucess: true
  31. }
  32. })
  33. },
  34. fail: function (error: any) {
  35. reject({
  36. data: {
  37. data: error,
  38. sucess: true
  39. }
  40. })
  41. },
  42. })
  43. })
  44. }

注意点:

在判断蓝牙是否打开之前,还要先判断下手机上位置是否打开

let locationEnabled = wx.getSystemInfoSync().locationEnabled

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/501205
推荐阅读
相关标签
  

闽ICP备14008679号