项目总结:微信小程序端实现蓝牙通信功能

前言

最近开发的小程序新增加了蓝牙通信功能,用于与一款蓝牙跳绳实现数据通信。主要功能点包括:

  1. 打开蓝牙并扫描设备
  2. 通过设备deviceId连接对应设备
  3. 小程序端下发指令,设置蓝牙跳绳模式(计时,计数,自由跳)
  4. 实时获取蓝牙广播的数据并进行解析

一、关于蓝牙协议

蓝牙(英语:Bluetooth),一种无线通讯技术标准,用来让固定与移动设备,在短距离间交换资料,以形成个人局域网(PAN)。

  • 蓝牙协议分为三种模式:

    • 高速蓝牙:主要用于数据交换与传输
    • 传统蓝牙:以基础信息沟通,设备连接为重点
    • 低功耗蓝牙:以不占用过多带宽的设备连接为主。在低功耗模式条件下,Bluetooth 4.0协议以上的蓝牙设备,传输距离可提升到100米以上(BLE)
  • 蓝牙服务UUID:

    • 通过蓝牙的UUID来标识 蓝牙服务与通讯访问的属性,不同的蓝牙服务和属性使用的是不同的方法,所以在获取到蓝牙服务时需要保持服务一致才能通信
    • 蓝牙的read,write,notification特征属性,都有对应的特征服务字段(同样是UUID)。
    • 厂商可以自定义蓝牙服务以及特征字段,因此实现蓝牙通信的前提是拿到确定的服务特征值
  • 蓝牙广播:

    • 蓝牙数据通过广播的形式实现通信,格式如长度+类型+内容,基内容可变,类型固定,长度由内容确定

二、关于微信小程序蓝牙模块API

官方文档地址:设备-蓝牙

主要用到API如下:

  1. 打开蓝牙适配器:wx.openBluetoothAdapter,后续所有蓝牙模块功能都需要先打开适配器才能进行
  2. 搜寻蓝牙设备:
    2.1 开始搜寻:wx.startBluetoothDevicesDiscovery,此功能比较消耗性能,如果搜索到特定设备可即时停止
    2.2 发现设备事件:wx.onBluetoothDeviceFound,在这儿添加实时更新设备列表业务代码
    2.3 停止扫描:wx.onBluetoothDeviceFound,停止扫描新的蓝牙设备,当蓝牙扫描到指令设备时,需要即时关闭扫描保证性能
    2.4 关闭发现设备事件监听:wx.offBluetoothDeviceFound
  3. 连接蓝牙设备: wx.createBLEConnection,通过传入蓝牙设备deviceId进行设备直连。这里的deviceId可通过上面扫描时wx.onBluetoothDeviceFound响应值获取
  4. 监听蓝牙设备连接状态:wx.onBLEConnectionStateChange: 包括开发者主动连接或断开连接,设备丢失,连接异常断开等等
  5. 获取蓝牙服务
    5.1 获取蓝牙低功耗设备所有服务: wx.getBLEDeviceServices,通过
    5.2 根据特定服务UUID查询所有特征:[wx.getBLEDeviceCharacteristics](wx.getBLEDeviceCharacteristics),
  6. 监听蓝牙数据(实时获取蓝牙跳绳回传的电量,跳绳数量等信息)
    6.1 订阅特征变化:wx.notifyBLECharacteristicValueChange,开启订阅后续才能监听到蓝牙数据变化
    6.2 监听特征值变化:wx.onBLECharacteristicValueChange,通过监听事件触发数据解析业务
  7. 发送数据(向蓝牙跳绳下发指令)
    7.1 下发指令:wx.writeBLECharacteristicValue,通过向蓝牙特定服务的对应特征值写入数据,完成交互。注意:要对应支持“write"属性的特征值
  8. 关闭蓝牙活动
    8.1 wx.stopBluetoothDevicesDiscovery(): 停止扫描新设备
    8.2 wx.offBluetoothDeviceFound():关闭扫描新设备监听事件
    8.3 wx.offBLECharacteristicValueChange():关闭特征值变化监听(数据监听)
    8.4 wx.offBLEConnectionStateChange():移除蓝牙低功耗连接状态改变事件的监听函数
    8.5 wx.closeBLEConnection: 断开蓝牙连接
    8.6 wx.closeBluetoothAdapter():关闭蓝牙适配器

三、蓝牙业务模块封装

因本小程序中的蓝牙跳绳应用场景有:扫描绑定,连接查询详情,实时跳绳数据传输等,所以实现蓝牙基类封装后,通过继承的方式来实现不同场景的使用需求。功能实现包括以下部分:

  1. 蓝牙模块封装:包括打开适配器,扫描,连接,实时数据传输
  2. 蓝牙业务中的工具处理函数:
    • 扫描到新设备时去重添加
    • 微信设备deviceId在安卓和ios下值格式是不同的(需求要展示为统一mac地址)所以需要特征处理
    • 蓝牙通信数据处理:16进制数据之前的互相转换

代码如下,篇幅有限进行了部分省略。

3.1 蓝牙基类

/**
 * 蓝牙跳绳基类,用于蓝牙相关通信均可继承
 */
import {
   
  inArray,	// 展示搜索到的设备列表时去重
  uuid2Mac, // 用于统一ios与android设备端展示的deviceId格式为:xx:xx:xx:xx:xx 
  deviceNameFilter,
  utf8to16,
  hexToString,
  ab2hex,
  str2ab,
} from "@/utils/util-BLE.js";

class BLEController {
   
  // 自动关闭定时器
  findTimer = null;
  // 蓝牙适配器开启状态
  static adapterOpend = false;
  // 扫描设备状态
  startDiscovery = false;
  // 蓝牙连接状态
  connectStatus = false;
  // 蓝牙扫描自动结束时间2min
  #timeout = 2 * 60 * 1000;
  // 蓝牙通信超时时间5min
  #notifyTimeout = 5 * 60 * 1000;
  // 蓝牙搜索是否超时
  deviceDiscoveryTimeout = false;
  // 蓝牙设备ID,注意:ios设置对应deviceId为设备uuid,安卓及开发者工具上连接的蓝牙为mac地址
  deviceId;
  deviceName;
  // 设备mac地址(统一编码处理)
  deviceMac;
  // 设备列表, [{deviceMac:设备mac地址, deviceId:设备ID,deviceName:设备名称,...}]
  deviceList = [];
  // 蓝牙服务特征队列
  characteristicStack = [];
  // 蓝牙消息队列
  msgStack = [];
  // 蓝牙通信serviceId
  serviceId = "";
  constructor(context) {
   
    if (context) {
   
      this.deviceId = context.deviceId;
      this.deviceMac = context.deviceMac;
      this.connectStatus = false;
    }
  }
  /**
   *  1.初始化蓝牙模块
   */
  openBluetoothAdapter() {
   
    const _this = this;
    if (BLEController.adapterOpend) {
   
      console.log("蓝牙适配器已打开,请勿重复操作------》");
      return;
    }
    wx.openBluetoothAdapter({
   
      mode: "central",
      success(res) {
   
        BLEController.adapterOpend = true;
        console.log("蓝牙适配器打开成功-----------------》");
      },
      fail(res) {
   
        BLEController.adapterOpend = false;
        _this.BLEFail(res);
        console.log("蓝牙适配器打开失败-----------------》", res.errMsg);
      },
    });
  }
  /**
   *  2.扫描蓝牙设备(绑定蓝牙,连接蓝牙通用)
   * @param {Array} options.keywords 蓝牙名称筛选关键字
   * @param {string} options.deviceId 可选参数,蓝牙设备id,连接用
   */
  startBluetoothDevicesDiscovery(options) {
   
    // ---------省略---------------》
    if (this.startDiscovery) {
   
      console.log("已开启蓝牙扫描,勿重复开启-----------》");
      return;
    } else {
   
      this.startDiscovery = true;
      wx.startBluetoothDevicesDiscovery({
   
        allowDuplicatesKey: false,
        success: (res) => {
   
          this.onBluetoothDeviceFound(options);
          console.log("开始扫描蓝牙设备-----------------》");
        },
        fail: (res) => {
   
          this.startDiscovery = false;
        },
      });
    }
  }
  /**
   *  2.1 监听搜索到新设备
   * @param {Array} options.keywords 蓝牙名称筛选关键字,来自startBluetoothDevicesDiscovery调用
   * @param {string} options.deviceId
   */
  onBluetoothDeviceFound(options) {
   
    let {
    keywords } = options;
    // 超时自动结束
    this.findTimer = setTimeout(() => {
   
      clearTimeout(this.findTimer);
      if (!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sophie_U

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值