微信小程序连接蓝牙

准备工作:

1:需要一个蓝牙板子和串口软件(卖蓝牙板子的商家会提供),手机上需要蓝牙调试助手(为了测试蓝牙是否正常连接)
2:蓝牙板通过usb插入到电脑端
3:安装好串口调试工具并打开连接上蓝牙
4:打开手机蓝牙调试助手,连接上后进行读写操作,确认已正常连接通信
准备工作完结!

直接上代码

第一步:初始化蓝牙设备, onShow里面调用或者onLoad里面调用都可,看你的需求场景

initBlue () {
    wx.openBluetoothAdapter({
      success: (res) => {
        wx.showToast({
          title: '正在搜索蓝牙设备...',
          icon: 'loading'
        })
        this.findBlue()
      },
      fail: (error) => {
        wx.showToast({
          title: '请开启蓝牙',
          icon: 'fails',
          duration: 1000
        })
        this.setData({ isTrigger: false })
      }
    })
  },

第二步:搜索蓝牙设备

findBlue(){
    wx.startBluetoothDevicesDiscovery({
      allowDuplicatesKey: true,
      interval: 0,
      powerLevel: 'high',
      success: (res) => {
        this.getBlue()//3.0
      },
      complete: () => {
        this.setData({ isTrigger: false })
      }
    })
  },

第三步:拿到需要的蓝牙设备进行列表渲染

getBlue () {
    wx.onBluetoothDeviceFound((devices) => {
      if (devices.devices[0].name.includes('demo')) {
        console.log(devices.devices[0].name, 'devices.devices[0].name')
        // 添加有名字的蓝牙设备,并去重处理
        this.setData({ bluetoolList: [...this.data.bluetoolList, devices.devices[0]].filter((obj, index, self) =>
          index === self.findIndex((t) => (
              t.name === obj.name
          ))) })
        wx.stopBluetoothDevicesDiscovery() // 停止搜索
      }
    })
  },

第四步:点击某个蓝牙设备进行连接

connetBluetooth(evt) {
    wx.showToast({
      title: '正在连接...',
      icon: 'loading'
    })
    console.log(evt.currentTarget.dataset, '=========')
    const { row } = evt.currentTarget.dataset
    this.setData({ currentDeviceid: row.deviceId })
    wx.setStorageSync('deviceId', row.deviceId)
    wx.createBLEConnection({
      deviceId: row.deviceId,
      timeout: 5000,
      success: (res) => {
        console.log('connet success: ', res)
        wx.stopBluetoothDevicesDiscovery()
        this.getServiceUUid() // 连接的收就获取服务ID 用于后面获取特征值id(特征值id可以用来进行读、写、监听蓝牙操作)
      },
      fail: (error) => {
        console.log('createBLEConnection error: ', error)
        if (error.errCode === -1) { // 表示已经连接, 直接跳转到对应页面即可
          wx.navigateTo({ url: '/pages/xxx/xxx' })
        } else {
          wx.showToast({
            title: '连接失败',
            icon: 'error',
            timeout: 500,
            complete: () => {
            }
          })
        }
      }
    })
  },

第五步:获取服务id,不同蓝牙设备,不同机型,获取的服务值不一样,根据你自己的蓝牙板子和机型来获取,一定要获取准确,错了就读写不了蓝牙设备

getServiceUUid() {
    console.log('=====================getServiceUUid=======================')
    let _this = this
    wx.getBLEDeviceServices({
      // 这里的 deviceid 需要已经通过 createBLEConnection 与对应设备建立链接
      deviceId: _this.data.currentDeviceid,
      success: async (res) => {
        console.log('res.services: ', res.services)
        if (wx.getStorageSync('platform') === 'ios') {
          // read
          await _this.setData({ readServiceId: res.services[0].uuid })
          await wx.setStorageSync('readServiceId', res.services[0].uuid)

          // write true
          await _this.setData({ writeServiceId: res.services[1].uuid })
          await wx.setStorageSync('writeServiceId', res.services[1].uuid)

          // notify
          await _this.setData({ notifyServiceId: res.services[1].uuid })
          await wx.setStorageSync('notifyServiceId', res.services[1].uuid)

          await _this.getReadCharacteIdIos()
          await _this.getWriteCharacteIdIos()

        } else {
          // read true
          // _this.setData({ readServiceId: res.services[0].uuid })
          await _this.setData({ readServiceId: res.services[2].uuid })
          await wx.setStorageSync('readServiceId', res.services[2].uuid)
  
          // 第一个 write: true;第二个 notify: true
          await _this.setData({ writeServiceId: res.services[1].uuid })
          await wx.setStorageSync('writeServiceId', res.services[1].uuid)

          await _this.setData({ notifyServiceId: res.services[1].uuid })
          await wx.setStorageSync('notifyServiceId', res.services[1].uuid)
  
          // read true
          // await _this.setData({ readServiceId: res.services[2].uuid })
          // await wx.setStorageSync('readServiceId', res.services[2].uuid)
          
          // indicate 安卓端监听不到蓝牙发送过来的回调
          // await _this.setData({ notifyServiceId: res.services[3].uuid })
          // await wx.setStorageSync('notifyServiceId', res.services[3].uuid)
  
          await _this.getReadCharacteId()
          // await _this.getNotifyCharacteId()
          await _this.getWriteCharacteId()
        }
      }
    })
  },

第六步:获取特征值id,并保证在了本地(也可以挂在全局,方便另一个页面获取),跳转到对应页面,这里你可以封装一下,我这里做demo就没封装,五个方法,分别获取IOS端和安卓端的对应读写和监听的特征值,一定要根据蓝牙的板子获取对应正确的特征值(为true的才能进行后面的连接和读写操作),慢慢调试

 // readServiceId
  getReadCharacteId() {
    let _this = this
    wx.getBLEDeviceCharacteristics({
      deviceId: _this.data.currentDeviceid,
      serviceId: _this.data.readServiceId,
      success: (res) => {
        console.log('res.haracteristics read: ', res.characteristics)
        for (let i = 0; i < res.characteristics.length; i++) {
          let characteristic = res.characteristics[i]
          // 检查特征值是否具有 read 属性为 false
          if (characteristic.properties.read) {
            // 当找到 read 属性为 false 的特征值时,设置 writeId 为该特征值的 UUID
            _this.setData({ characteReadId: characteristic.uuid })
            wx.setStorageSync('characteReadId', characteristic.uuid)
            // break // 找到符合条件的特征值后,结束循环
          }
        }
      },
      fail: (error) => {
        console.log('get read CharacteId error: ', error)
      }
    })
  },
  // use bluetool deviceId and uuid get characteId (特征值) writeServiceId
  getWriteCharacteId () {
    let _this = this
    wx.getBLEDeviceCharacteristics({
      deviceId: _this.data.currentDeviceid,
      serviceId: _this.data.writeServiceId,
      success: (res) => {
        // 遍历特征值列表
        console.log('res.characteristics write : ', res.characteristics)
        for (let i = 0; i < res.characteristics.length; i++) {
          let characteristic = res.characteristics[i]
          // 检查特征值是否具有 read 属性为 false
          if (characteristic.properties.write) {
            // 当找到 read 属性为 false 的特征值时,设置 writeId 为该特征值的 UUID
            _this.setData({
              characteWriteId: characteristic.uuid
            })
            wx.setStorageSync('characteWriteId', characteristic.uuid)
            // break // 找到符合条件的特征值后,结束循环
          }
          if (characteristic.properties.notify) {
            _this.setData({ characteNotifyId: characteristic.uuid })
            wx.setStorageSync('characteNotifyId', characteristic.uuid)
          }
        }
        console.log('currentDeviceid: ', _this.data.currentDeviceid)
        console.log('----------------------read--------------------')
        console.log('readServiceId: ', _this.data.readServiceId)
        console.log('characteReadId: ', _this.data.characteReadId)
        console.log('----------------------write--------------------')
        console.log('writeServiceId: ', _this.data.writeServiceId)
        console.log('characteWriteId: ', _this.data.characteWriteId)
        wx.navigateTo({
          url: '/pages/action/action'
        })
        wx.hideToast()
      },
      fail: function (error) {
        console.log("error reason: ", error)
      }
    })
  },
  // notifyServiceId
  getNotifyCharacteId() {
    let _this = this
    wx.getBLEDeviceCharacteristics({
      deviceId: _this.data.currentDeviceid,
      serviceId: _this.data.notifyServiceId,
      success: (res) => {
        console.log('res.characteristics notify: ', res.characteristics)
        for (let i = 0; i < res.characteristics.length; i++) {
          let characteristic = res.characteristics[i]
          // 检查特征值是否具有 read 属性为 false
          if (characteristic.properties.indicate) {
            // 当找到 read 属性为 false 的特征值时,设置 writeId 为该特征值的 UUID
            _this.setData({ characteNotifyId: characteristic.uuid })
            wx.setStorageSync('characteNotifyId', characteristic.uuid)
            break // 找到符合条件的特征值后,结束循环
          }
        }
      },
      fail: (error) => {
        console.log('get notify CharacteId error: ', error)
      }
    })
  },

  // ios read characteId
  getReadCharacteIdIos() {
    wx.getBLEDeviceCharacteristics({
      deviceId: this.data.currentDeviceid,
      serviceId: this.data.readServiceId,
      success: (res) => {
        // 遍历特征值列表
        console.log('res.characteristics read : ', res.characteristics)
        for (let i = 0; i < res.characteristics.length; i++) {
          let characteristic = res.characteristics[i]
          // 检查特征值是否具有 read 属性为 false
          if (characteristic.properties.read) {
            // 当找到 read 属性为 false 的特征值时,设置 writeId 为该特征值的 UUID
            this.setData({
              characteReadId: characteristic.uuid
            })
            wx.setStorageSync('characteReadId', characteristic.uuid)
            break // 找到符合条件的特征值后,结束循环
          }
        }
      }
    })
  },
  // ios write characteId
  getWriteCharacteIdIos() {
    wx.getBLEDeviceCharacteristics({
      deviceId: this.data.currentDeviceid,
      serviceId: this.data.writeServiceId,
      success: (res) => {
        // 遍历特征值列表
        console.log('res.characteristics write : ', res.characteristics)
        for (let i = 0; i < res.characteristics.length; i++) {
          let characteristic = res.characteristics[i]
          // 检查特征值是否具有 read 属性为 false
          if (characteristic.properties.write) {
            // 当找到 read 属性为 false 的特征值时,设置 writeId 为该特征值的 UUID
            this.setData({
              characteWriteId: characteristic.uuid
            })
            wx.setStorageSync('characteWriteId', characteristic.uuid)
            // break // 找到符合条件的特征值后,结束循环
          }
          if (characteristic.properties.notify) {
            // 当找到 read 属性为 false 的特征值时,设置 writeId 为该特征值的 UUID
            this.setData({
              characteNotifyId: characteristic.uuid
            })
            wx.setStorageSync('characteNotifyId', characteristic.uuid)
          }
          wx.navigateTo({
            url: '/pages/xxx/xxx'
          })
          wx.hideToast()
        }
      }
    })
  },

第七步:这时候已经跳转到对应页面了,在页面onLoad里开启监听,后面蓝牙发送设备到小程序可以实时监听到值

async onLoad(options) {
    // 监听蓝牙发送到小程序的数据
    await wx.onBLECharacteristicValueChange((res) => {
      console.log('characteristicis: ', res.value)
      console.log('转换后的值: ', this.ab2hex(res.value))
      this.setData({ fromBlueToolsData: this.ab2hex(res.value) })
      // this.setData({ fromBlueToolsData: res.value })
    })

    await wx.readBLECharacteristicValue({
      deviceId: wx.getStorageSync('deviceId'),
      serviceId: wx.getStorageSync('readServiceId'),
      characteristicId: wx.getStorageSync('characteReadId'),
      success: (res) => {
        console.log('read data is: ', res)
      },
      fail: (error) => {
        console.log('read error, error message is: ', error)
      }
    })

    await wx.notifyBLECharacteristicValueChange({
      state: true,
      type: 'notification', // 根据你蓝牙的特征值来选择类型
      deviceId: wx.getStorageSync('deviceId'),
      serviceId: wx.getStorageSync('notifyServiceId'),
      characteristicId: wx.getStorageSync('characteNotifyId'),
      success: (res) => {
        console.log('notify success, success message is: ', res)
      },
      fail: (error) => {
        console.log('notify error, error message is: ', error)
        this.setData({ fromBlueToolsData: '' })
      }
    })
  },

  // 16 进制到 10进制
  ab2hex(buffer) {
    let hexArr = Array.prototype.map.call(
      new Uint8Array(buffer),
      function(bit) {
        return ('00' + bit.toString(16)).slice(-2)
      }
    )
    return hexArr.join('');
  },

第八步:测试读写,看蓝牙串口与小程序是否有通信

// 写入数据
writeTap() {
    console.log('-----------------start write action----------------------------')
    console.log('inputValue: ', this.data.inputValue)
    let data = this.data.inputValue
    if (data.length === 0) {
      wx.showModal({ title: '提示', content: '请输入要发送的数据' })
      return
  }
    wx.writeBLECharacteristicValue({
      deviceId: wx.getStorageSync('deviceId'),
      serviceId: wx.getStorageSync('writeServiceId'),
      characteristicId: wx.getStorageSync('characteWriteId'),
      value: this.string2buffer(data), // 数据转换发送
      success (res) {
        console.log('writeBLECharacteristicValue success', res)
        this.setData({ inputValue: '' })
      },
      fail: (error) => {
        console.log('write error, error message is: ', error)
      }
    })
  },
  string2buffer(hexString) {
    hexString = hexString.replace(/^0x/, '');
    const bytes = new Uint8Array(hexString.length / 2);
    for (let i = 0; i < hexString.length; i += 2) {
        bytes[i / 2] = parseInt(hexString.substring(i, i + 2), 16);
    }
    console.log('写入的buffer:', bytes.buffer)
    return bytes.buffer;
  },
  // input输入值
  onWriteInput(evt) {
    const { value } = evt.detail
    this.setData({ inputValue: value })
  },

最终测试后在ios与安卓上能够与蓝牙串口进行正常通信,完结!

相关推荐
博客zhu虎康3 分钟前
ElementUI 的 form 表单校验
前端·javascript·elementui
407指导员12 分钟前
uniapp 微信小程序 页面部分截图实现
微信小程序·小程序·uni-app
cronaldo9124 分钟前
研发效能DevOps: Vite 使用 Element Plus
vue.js·vue·devops
敲啊敲952731 分钟前
5.npm包
前端·npm·node.js
CodeClimb41 分钟前
【华为OD-E卷-木板 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
咸鱼翻面儿1 小时前
Javascript异步,这次我真弄懂了!!!
javascript
brrdg_sefg1 小时前
Rust 在前端基建中的使用
前端·rust·状态模式
m0_748230941 小时前
Rust赋能前端: 纯血前端将 Table 导出 Excel
前端·rust·excel
qq_589568101 小时前
Echarts的高级使用,动画,交互api
前端·javascript·echarts