最近很闲,但是行业很卷!因为公司有硬件设备对接,但是介于原生app。闲来无事,便研究了下这个小程序通过蓝牙与硬件设备进行通讯。废话少说上干货!

本次讲解的目录大致分为三模块。根据我写的代码做讲解。

  • 初始化并搜索蓝牙

  • 获取并启用service服务

  • 数据读取初始化并监听设备返回的数据

html部分

js逻辑部分-分开讲解

页面进来是需要初始化的date中的数据,所以需要在onload中执行

onload中的初始化代码-就是设置列表高度、蓝牙列表的初始化

其中初始化最后面有一段代码注释也写得很明确了,第一种的过滤出你设置好的蓝牙,第二种反之。

在onHide事件就是--重置清空

接下来就是事件逻辑了!!!

我们这里罗列下uniapp官网提供的接下来需要用到的api

// 关闭蓝牙uni.closeBluetoothAdapter({})// 打开蓝牙uni.openBluetoothAdapter({})// 搜索附近的蓝牙uni.startBluetoothDevicesDiscovery({})// 停止搜索uni.stopBluetoothDevicesDiscovery({})// 连接低功耗BLE蓝牙uni.createBLEConnection({})// 获取蓝牙设备所有服务(service)uni.getBLEDeviceServices({})// 获取蓝牙特征值uni.getBLEDeviceCharacteristics({})// 启用低功耗蓝牙设备特征值变化时的 notify 功能,订阅特征值uni.notifyBLECharacteristicValueChange({})// 监听低功耗蓝牙设备的特征值变化事件uni.onBLECharacteristicValueChange({})// 读取低功耗蓝牙设备的特征值的二进制数据值uni.readBLECharacteristicValue({})

我是把各个事件归总到三个事件里面去执行了。没有分事件来讲解,见谅

首先,是搜索蓝牙:搜索蓝牙里面需用到的就是,关闭蓝牙-打开蓝牙-搜索蓝牙-停止搜索。

搜索成功后点击蓝牙列表进行连接

紧接着获取蓝牙设备所有服务(service)及相关的格式转换

启动所有服务(service)后,进行蓝牙读取的初始化并监听

附上代码,希望对大家有所帮助。全文干货满满,实战,文章附上实战视频​。

<template>  <view class="device">    <scroll-view scroll-y :style="'width:500rpx;height:' + list_height + 'rpx'">      <block v-for="(item, index) in devicesList" :key="index">        <view class="list-item" :id="item.deviceId" @tap="Connect">          <view style="display: flex; flex-direction: column; width: 80%">            <text style="font-size: medium; word-break: break-all"              >设备名称: {{ item.name }}</text            >            <text style="font-size: x-small; color: gray; word-break: break-all"              >设备ID: {{ item.deviceId }}</text            >            <text style="font-size: x-small; color: gray; word-break: break-all"              >信号强度RSSI: {{ item.RSSI }}</text            >          </view>          <image            style="width: 36px; height: 36px"            mode="aspectFit"            src="/static/images/bluetooth.png"          ></image>        </view>      </block>    </scroll-view>    <button      type="primary"      class="button"      :loading="searching"      @tap="Search"      style="margin-bottom: 10px"    >      {{ searching ? '搜索中...' : '1.搜索蓝牙设备' }}    </button>    <button      type="primary"      class="button"      @click="getBLEDeviceServices"      style="margin-bottom: 10px"    >      2.获取servies服务    </button>    <button      type="primary"      class="button"      :loading="initLoading"      @click="readBluetoothAdapter"      style="margin-bottom: 10px"    >      3.初始化数据    </button>  </view></template><script>const app = getApp()export default {  data () {    return {      searching: false,      deviceName: 'EV-IC-1961B', // 指定蓝牙名称      deviceId: null, // 设备id      services: null, // services服务      connectedDeviceId: null, // 记录设备id      notifyCharacteristicsId: null, // 蓝牙特征值      balanceData: null, // 转换的格式      notifyServicweId: null, // 特征id      hexstr: null, // 转换格式      devicesList: [], // 列表      list_height: '',      initLoading: false    }  },  onLoad () {    var that = this    var list_height =      (app.globalData.SystemInfo.windowHeight - 200) *        (750 / app.globalData.SystemInfo.windowWidth) -      60    that.$set(that, 'list_height', list_height)    uni.onBluetoothAdapterStateChange(function (res) {      that.$set(that, 'searching', res.discovering)      if (!res.available) {        that.$set(that, 'searching', false)      }    })    that.$set(that, 'list_height', list_height)    uni.onBluetoothAdapterStateChange(function (res) {      that.$set(that, 'searching', res.discovering)      if (!res.available) {        that.$set(that, 'searching', false)      }    })    uni.onBluetoothDeviceFound(function (devices) {      //剔除重复设备,兼容不同设备API的不同返回值      var isnotexist = true      if (devices.deviceId) {        if (devices.advertisData) {          devices.advertisData = app.globalData.buf2hex(devices.advertisData)        } else {          devices.advertisData = ''        }        for (var i = 0; i < that.devicesList.length; i++) {          if (devices.deviceId == that.devicesList[i].deviceId) {            isnotexist = false          }        }        if (isnotexist) {          that.devicesList.push(devices)        }      } else if (devices.devices) {        if (devices.devices[0].advertisData) {          devices.devices[0].advertisData = app.globalData.buf2hex(            devices.devices[0].advertisData          )        } else {          devices.devices[0].advertisData = ''        }        for (var i = 0; i < that.devicesList.length; i++) {          if (devices.devices[0].deviceId == that.devicesList[i].deviceId) {            isnotexist = false          }        }        if (isnotexist) {          that.devicesList.push(devices.devices[0])        }      } else if (devices[0]) {        if (devices[0].advertisData) {          devices[0].advertisData = app.globalData.buf2hex(            devices[0].advertisData          )        } else {          devices[0].advertisData = ''        }        // console.log(devices[0])        for (var i = 0; i < devices_list.length; i++) {          if (devices[0].deviceId == that.devicesList[i].deviceId) {            isnotexist = false          }        }        if (isnotexist) {          that.devicesList.push(devices[0])        }      }      let devList = []      // 专用名称 意思是只有这名字才显示出来      // that.devicesList.forEach(item=>{      //   if(item.name == that.deviceName){      //     that.deviceId = item.deviceId; // 直接获取指定设备的id      //     devList.push(item)      //   }      // })      // 有设备名 意思是有设备名就显示      that.devicesList.forEach(item => {        if (item.name) {          devList.push(item)        }      })      // that.$set(that, 'devicesList', that.devicesList)      that.$set(that, 'devicesList', devList) // 过滤    })  },  onHide: function () {    var that = this    that.$set(that, 'devicesList', [])    if (this.searching) {      uni.stopBluetoothDevicesDiscovery({        success: function (res) {          that.$set(that, 'searching', false)        }      })    }  },  methods: {    // 搜索设备    Search: function () {      var that = this      if (!that.searching) {        // 关闭蓝牙        uni.closeBluetoothAdapter({          complete: function (res) {            // 打开蓝牙            uni.openBluetoothAdapter({              success: function (res) {                // 搜索蓝牙                uni.startBluetoothDevicesDiscovery({                  allowDuplicatesKey: false,                  success: function (res) {                    that.$set(that, 'searching', true)                    that.$set(that, 'devicesList', [])                    setTimeout(() => {                      // 停止搜索                      uni.stopBluetoothDevicesDiscovery({                        success: function (res) {                          uni.showToast({                            title: '搜索完成',                            icon: 'success',                            duration: 500                          })                          that.$set(that, 'searching', false)                        }                      })                    }, 2000)                  }                })              },              fail: function (res) {                uni.showModal({                  title: '提示',                  content: '请检查手机蓝牙是否打开',                  showCancel: false,                  success: function (res) {                    that.$set(that, 'searching', false)                  }                })              }            })          }        })      } else {        uni.stopBluetoothDevicesDiscovery({          success: function (res) {            that.$set(that, 'searching', false)          }        })      }    },    // 5连接蓝牙Connect connectTO    Connect (e) {      var that = this      uni.showLoading({        title: '连接蓝牙设备中...'      })      that.deviceId = e.currentTarget.id // 这里是做非指定设备的兼容赋值      console.log('设备id', that.deviceId)      app.globalData.deviceId = that.deviceId      uni.createBLEConnection({        deviceId: that.deviceId, // 蓝牙设备id        success: function (res) {          that.connectedDeviceId = that.deviceId          uni.hideLoading()          uni.showToast({            title: '连接成功',            icon: 'success',            duration: 1000          })        },        fail: function (res) {          uni.hideLoading()          uni.showModal({            title: '提示',            content: '连接失败',            showCancel: false          })        }      })    },    // 6获取蓝牙设备的service服务    getBLEDeviceServices () {      var that = this      uni.getBLEDeviceServices({        deviceId: that.deviceId || app.globalData.deviceId,        success: function (res) {          uni.showToast({            title: '启动成功',            icon: 'success',            duration: 1000          })          that.services = res.services // 拿到数组对象          /* 获取连接设备的所有特征值 */          that.getBLEDeviceCharacteristics()        },        fail: error => {          console.log(error, '错误反馈')        }      })    },    // 7获取蓝牙设备特征值    getBLEDeviceCharacteristics () {      var that = this      // console.log(that.services,'that.services');  // 拿到了数据      uni.getBLEDeviceCharacteristics({        //   deviceId: that.connectedDeviceId,        deviceId: that.deviceId || app.globalData.deviceId,        serviceId: that.services[0].uuid,        success: function (res) {          console.log(res, 'res')          for (var i = 0; i < res.characteristics.length; i++) {            if (              (res.characteristics[i].properties.notify ||                res.characteristics[i].properties.indicate) &&              res.characteristics[i].properties.read &&              res.characteristics[i].properties.write            ) {              console.log(res.characteristics[i].uuid, '蓝牙特征值 ==========') // 已获得              /* 获取蓝牙特征值 */              that.notifyCharacteristicsId = res.characteristics[i].uuid              // 启用低功耗蓝牙设备特征值变化时的 notify 功能              that.notifyBLECharacteristicValueChange()            }          }        },        fail: function (res) {}      })    },    // 启动notify 蓝牙监听功能 后使用 wx.onBLECharacteristicValueChange用来监听蓝牙设备传递数据    // 接收到的数据和发送的数据必须是二级制数据, 页面展示的时候需要进行转换    notifyBLECharacteristicValueChange () {      // 启用低功耗蓝牙设备特征值变化时的 notify 功能      var that = this      console.log('6.启用低功耗蓝牙设备特征值变化时的 notify 功能')      uni.notifyBLECharacteristicValueChange({        state: true,        deviceId: that.deviceId || app.globalData.deviceId,        serviceId: that.services[0].uuid, // 蓝牙特征值对应服务的 uuid        characteristicId: that.notifyCharacteristicsId,        complete (res) {          console.log('7启用低功耗蓝牙设备监听成功')          /*用来监听手机蓝牙设备的数据变化*/          uni.onBLECharacteristicValueChange(function (res) {            /**/            that.balanceData += that.buf2string(res.value)            that.hexstr += that.receiveData(res.value)          })        },        fail (res) {          console.log(res, '启用低功耗蓝牙设备监听失败')        }      })    },    /*转换成需要的格式*/    buf2string (buffer) {      var arr = Array.prototype.map.call(new Uint8Array(buffer), x => x)      return arr        .map((char, i) => {          return String.fromCharCode(char)        })        .join('')    },    receiveData (buf) {      return this.hexCharCodeToStr(this.ab2hex(buf))    },    /*转成二进制*/    ab2hex (buffer) {      var hexArr = Array.prototype.map.call(        new Uint8Array(buffer),        function (bit) {          return ('00' + bit.toString(16)).slice(-2)        }      )      return hexArr.join('')    },    /*转成可展会的文字*/    hexCharCodeToStr (hexCharCodeStr) {      var trimedStr = hexCharCodeStr.trim()      var rawStr =        trimedStr.substr(0, 2).toLowerCase() === '0x'          ? trimedStr.substr(2)          : trimedStr      var len = rawStr.length      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('')    },    // 读取蓝牙传输的数据    readBluetoothAdapter () {      var that = this      that.initLoading = true      // 必须在这里的回调才能获取      uni.onBLECharacteristicValueChange(function (characteristic) {        console.log(that.buf2string(characteristic.value), '16进制解析')      })      uni.readBLECharacteristicValue({        // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接        deviceId: that.deviceId || app.globalData.deviceId,        // 这里的 serviceId 需要在上面的 getBLEDeviceServices 接口中获取        serviceId: that.services[0].uuid,        // 这里的 characteristicId 需要在上面的 getBLEDeviceCharacteristics 接口中获取        characteristicId: that.notifyCharacteristicsId,        success: function (res) {          console.log('readBLECharacteristicValue:', res) // ok        }      })      setTimeout(() => {        that.initLoading = false        uni.showToast({          title: '初始化成功',          icon: 'success'        })      }, 2000)    }    // 在向蓝牙设备传递数据和接收数据的过程中,并未使用到read的API 不知道有没有潜在的问题,目前线上运行为发现任何的问题  }}</script><style>.device {  padding: 0 15px;}</style>

视频链接:小程序蓝牙设备数据对接实战

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐