IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 小程序蓝牙连接低功耗设备(BLE)记录 -> 正文阅读

[移动开发]小程序蓝牙连接低功耗设备(BLE)记录

第一步 查询是否授权蓝牙 授权后初始化蓝牙 获取本机蓝牙状态 开启监听蓝牙开启关闭事件 若不调用openBluetoothAdapter方法 下面无法进行

代码中bluetooth 为封装的一些公共方法 会写在最下面

bluetooth.getBluetoothSetting().then(() => {
      //已授权 初始化蓝牙模块
      wx.openBluetoothAdapter({
        success: () => {},
        fail: err => bluetooth.errorCodeToStr(err),
        complete: () => {
          wx.hideLoading()
          this.setData({
            bluetoothInit: true
          })
          // 获取本机蓝牙适配器状态。
          wx.getBluetoothAdapterState().then(res => {
            this.setData({
              bluetoothAvailable: res.available,
            })
          }).catch(err => bluetooth.errorCodeToStr(err))
          // 监听蓝牙适配器状态变化事件 是否开启蓝牙
          wx.onBluetoothAdapterStateChange((res) => {
            let page = getCurrentPages()
            if (page[page.length - 1].route != 'pages/index/index') return
            wx.showToast({
              title: '蓝牙已' + (res.available ? '开启' : '关闭'),
              icon: 'none'
            })
            this.setData({
              bluetoothAvailable: res.available,
            })
          })
        }
      })
    }).catch(err => {
      wx.showToast({
        title: err,
        icon: 'none'
      })
    })

第二步 搜索低功耗蓝牙设备 和停止搜索 搜索到的设备添加到列表 点击列表选择想要连接的蓝牙设备 (列表点击事件没写 自己写就行)

let timer=null  
// 开始搜索蓝牙设备 10秒后自动停止 也可以手动停止搜索
  starSearch() {
    wx.hideLoading()
    wx.startBluetoothDevicesDiscovery({
      allowDuplicatesKey: false
    }).then(res => {
      this.setData({
        status: 1
      })
      // 定时结束搜索
      timer = setTimeout(() => {
        this.stopSearch()
      }, 10000)
    }).catch(err => bluetooth.errorCodeToStr(err))
    // 监听搜索到新设备的事件 添加到列表
    wx.onBluetoothDeviceFound((res) => {
      var devices = res.devices[0];
      if (devices.name) {
        this.setData({
          list: [...this.data.list, devices]
        })
      }
    })
  },
  // 停止搜索(可手动调用)
  stopSearch() {
    wx.hideLoading()
   //清除计时器
    clearTimeout(timer)
   //取消监听寻找到新设备的事件
    wx.offBluetoothDeviceFound()
    //停止搜寻附近的蓝牙外围设备 判断设备数量做出提示
    wx.stopBluetoothDevicesDiscovery().then(res => {
      let status = (this.data.list.length < 1 ? 2 : 3)
      this.setData({
        status: status
      })
      if (status == 2) {
        wx.showModal({
          title: '提示',
          content: '未检测到设备,请打开设备重试~',
          showCancel: false
        })
      }
    }).catch(err => bluetooth.errorCodeToStr(err))
  },

第三步? 创建蓝牙连接获取所需要deviceId(搜索到设备时获取)?serviceId(isPrimary=true的那个uuid),characteristicId(这个是需要characteristics中 write为true时 为写入时需要用到的uuid 若需要监听上报信息 需要选择notify为true的uuid)就是个概念 具体参考官方文档结合自己控制台打印的去判断

当蓝牙连接成功后可以把蓝牙设备的数据 存到缓存或者别的位置 方便下次直接试用

原文:

createBLEConnection 连接蓝牙低功耗设备。

若小程序在之前已有搜索过某个蓝牙设备,并成功建立连接,可直接传入之前搜索获取的 deviceId 直接尝试连接该设备,无需再次进行搜索操作。

// 创建蓝牙连接
  createMachineLink() {
    // 连接前 断开与其他蓝牙低功耗设备的连接
    wx.showLoading({
      title: '连接中...',
      mask: true
    })
    // 监听断开连接
    wx.onBLEConnectionStateChange((res) => {
      if (!res.connected)
        this.setData({
          isLink: res.connected,
        })
    })

    wx.createBLEConnection({
      deviceId: this.data.deviceId,
      timeout: 5000,
    }).then(() => {
      // 获取蓝牙低功耗设备所有服务 (service)
      wx.getBLEDeviceServices({
        deviceId: this.data.deviceId
      }).then(servicesData => {
        this.setData({
          serviceId: servicesData.services[0].uuid
        }, () => {
          // 获取蓝牙低功耗设备某个服务中所有特征 (characteristic)
          wx.getBLEDeviceCharacteristics({
            deviceId: this.data.deviceId,
            serviceId: this.data.serviceId,
          }).then(res => {
            wx.setStorageSync('leaveStatus', 'link')
            wx.showToast({
              title: '连接成功',
            })
            this.setData({
              isLink: true,
              writeCharacteristicId: res.characteristics.find(item => item.properties.write == true).uuid,
              notifyCharacteristicId: res.characteristics.find(item => item.properties.notify == true).uuid
            }, () => this.notifyBluetoothListener())
          }).catch(err => bluetooth.errorCodeToStr(err))
        })
      }).catch(err => bluetooth.errorCodeToStr(err))
    }).catch(err => bluetooth.errorCodeToStr(err))
  },

第四步? ?写入数据 我这里直接封装的方法 可以参考(这个是需要传入10字节 的16进制字符串)我这个只是参考

bluetooth.writeData(this.data.deviceId, this.data.serviceId, this.data.writeCharacteristicId, '044000')

//封装
  // 写入数据
  writeData(deviceId, serviceId, characteristicId, value) {
    wx.writeBLECharacteristicValue({
      deviceId,
      serviceId,
      characteristicId,
      value: this.createBuffer(value),
    }).then(res => {
      setTimeout(() => {
        wx.hideLoading()
      }, 700)
    }).catch(err => this.errorCodeToStr(err))
  },
  // 创建10位 0x00 16进制数据
  createBuffer(num) {
    let buffer = new ArrayBuffer(10);
    let dataView = new DataView(buffer);
    // 固定头
    dataView.setUint8(0, 0x0D);
    dataView.setUint8(1, 0x02);
    // 固定头尾
    dataView.setUint8(8, 0x0D);
    dataView.setUint8(9, 0x03);
    for (let i in num) {
      dataView.setUint8(parseInt(i) + 2, ('0x' + num[i].charCodeAt().toString(16)));
    }
    return dataView.buffer
  },

第五步 监听蓝牙上报信息 解码并做出相应处理

// 监听 设备上报
  notifyBluetoothListener() {
    wx.showLoading({
      title: '获取状态中...',
      mask: true
    })
    //  启用蓝牙低功耗设备特征值变化时的 notify 功能
    wx.notifyBLECharacteristicValueChange({
      state: true,
      deviceId: this.data.deviceId,
      serviceId: this.data.serviceId,
      characteristicId: this.data.notifyCharacteristicId,
    }).then(res => {
      // 启用成功 下发指令 获取 设备状态
      bluetooth.writeData(this.data.deviceId, this.data.serviceId, this.data.writeCharacteristicId, '018000')
    }).catch(err => bluetooth.errorCodeToStr(err))

    // 必须先启用 wx.notifyBLECharacteristicValueChange 才能监听到设备 characteristicValueChange 事件
    wx.onBLECharacteristicValueChange((res) => {
      setTimeout(() => {
        this.setData({
          writeType: false
        })
      }, 1000)

      if (res.value.length >= 11) {
        bluetooth.closeBLEConnection(this.data.deviceId)
        wx.showToast({
          title: '未知错误',
        })
        return
      }
      this.handleValueChange(bluetooth.ab2hex(res.value))
    })
  },
  // 上报结果处理
  handleValueChange(str) {
    // 去除固定头固定尾
    let hex = str.substring(4,str.length-4)
    hex = bluetooth.hexCharCodeToStr(hex)
    if (!hex) {
      wx.showToast({
        title: '未知错误',
      })
      return
    }
    let status = Number('0x' + (hex.substring(0, 2)))

    if (!status) {
      bluetooth.closeBLEConnection(this.data.deviceId)
      wx.showToast({
        title: '未知错误',
      })
      return
    }

    this.setData({
      isRun: (status >> 6) & 1, //是否运行中
      isHot: (status & 1), //加热
      speed: (status >> 2) & 3, //速度
      mode: (status >> 4) & 3, //模式
    })
  },

这里 封装的上面代码中所用的的方法

module.exports = {
  // 创建10位 0x00 16进制数据
  createBuffer(num) {
    let buffer = new ArrayBuffer(10);
    let dataView = new DataView(buffer);
    // 固定头
    dataView.setUint8(0, 0x0D);
    dataView.setUint8(1, 0x02);
    // 固定头尾
    dataView.setUint8(8, 0x0D);
    dataView.setUint8(9, 0x03);
    for (let i in num) {
      dataView.setUint8(parseInt(i) + 2, ('0x' + num[i].charCodeAt().toString(16)));
    }
    return dataView.buffer
  },
  // 写入数据
  writeData(deviceId, serviceId, characteristicId, value) {
    wx.writeBLECharacteristicValue({
      deviceId,
      serviceId,
      characteristicId,
      value: this.createBuffer(value),
    }).then(res => {
      setTimeout(() => {
        wx.hideLoading()
      }, 700)
    }).catch(err => this.errorCodeToStr(err))
  },
  // 断开蓝牙连接
  closeBLEConnection(deviceId, type) {
    wx.closeBLEConnection({
      deviceId: deviceId,
      success: () => {
        if (type)
          wx.showToast({
            title: '断开连接',
            icon: 'none'
          })
      },
      fail: err => this.errorCodeToStr(err, type)
    })
  },
  //蓝牙授权查询
  getBluetoothSetting() {
    return new Promise((resolve, reject) => {
      wx.getSetting().then(res => {
        if (!res.authSetting['scope.bluetooth']) {
          this.scopeBluetooth().then(data => {
            resolve(data)
          }).catch(err => reject(err))
        } else {
          resolve(res.authSetting)
        }
      }).catch(err => reject('getSetting error'))
    })
  },
  //申请蓝牙授权
  scopeBluetooth() {
    return new Promise((resolve, reject) => {
      wx.authorize({
        scope: 'scope.bluetooth',
        success(res) {
          resolve(res)
        },
        fail(err) {
          wx.showModal({
            title: '提示',
            content: '请授权蓝牙,以便使用设备',
            success(res) {
              if (res.cancel) {
                reject('未授权蓝牙')
                return
              }
              wx.openSetting({
                success(data) {
                  if (data.authSetting['scope.bluetooth']) {
                    resolve(data.authSetting)
                  } else {
                    reject('未授权蓝牙')
                  }
                }
              })
            }
          })
        }
      })
    })
  },
  // 蓝牙错误统一处理
  errorCodeToStr(err, type) {
    console.log(err)

    if (!err.errCode) {
      console.log(err.errMsg)
      return
    }
    if (type) return
    wx.showToast({
      title: this.codeToStr[err.errCode],
      icon: 'none'
    })
  },
  codeToStr: {
    "0": "正常",
    "-1": "已连接",
    "10000": "未初始化蓝牙适配器",
    "10001": "当前蓝牙适配器不可用",
    "10002": "没有找到指定设备",
    "10003": "连接失败",
    "10004": "没有找到指定服务",
    "10005": "没有找到指定特征",
    "10006": "当前连接已断开",
    "10007": "当前特征不支持此操作",
    "10008": "其余所有系统上报的异常",
    "10009": "Android 系统特有,系统版本低于 4.3 不支持 BLE",
    "10012": "连接超时",
    "10013": "连接 deviceId 为空或者是格式不正确",
  },
  // ArrayBuffer转16进制字符串
  ab2hex(buffer) {
    let hexArr = Array.prototype.map.call(
      new Uint8Array(buffer),
      function (bit) {
        return ('00' + bit.toString(16)).slice(-2)
      }
    )
    return hexArr.join('');
  },
  // ArrayBuffer转16进制字符串转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("存在非法字符!");
      return "";
    }
    var curCharCode;
    var resultStr = [];
    for (var i = 0; i < len; i = i + 2) {
      curCharCode = parseInt(rawStr.substr(i, 2), 16);
      resultStr.push(String.fromCharCode(curCharCode));
    }
    return resultStr.join("");
  },
}

此文章 只是大概记录? 以便再次遇到类似项目能有些经验? 希望能给看到这篇文章的人提供一些帮助?

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-04-22 18:47:44  更:2022-04-22 18:49:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 21:31:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码