微信小程序ble模块封装成工具类(附源码)

前言:

20190429更新,新开发了一个库,如果你是android开发者你可能需要: 一个基于rxjava2的AndroidBle库-RxAndroidBluetooth

2020/03/06更新,最近在使用中发现如果在页面进入时自动开启扫描的情况下,工具类没有提供很好的契机支持,所以我修改了一下部分代码,在bleStateListener方法中新增了一个状态用来监听蓝牙适配器初始化成功的回调,在该状态触发后调用者可开启扫描,此时扫描一定可用

2020/03/09更新,补充2个问题,1.如果你在调试过程中发现断开连接的回调没有收到,你需要确定notify是否确定开启,开启之后才能接收到断开的回调,不知道小程序的文档为什么没有明确说明这个问题
2.部分手机小程序搜索不到蓝牙,这是微信需要位置权限(6.0以上安卓手机)

2020/03/20更新,最近主要调ios方面,在蓝牙方面的api上很多回调和android还是有一些差异的,调完之后也没有一一记录,我记忆比较深刻的是ios不能重复初始化适配器,否则会导致初始化函数无回调(概率大概为三分之一),我在论坛上看到有些人也遇到这个问题,不过我没有去告诉他们真相(哈哈),初始化适配器应该是全局唯一的,我们可以先获取适配器状态再根据状态决定是否初始化适配器以应对多个页面使用蓝牙功能,伪代码如下:

 wx.getBluetoothAdapterState({
    success: res => {
      //ios 蓝牙适配器没有初始化会走这里
      if (!res.available) {
        console.log('ios 蓝牙适配器没有初始化会走这里')
        _initBluetoothAdapter()
      } else {
        console.log('蓝牙适配器已初始化 android ios都会走这里')
      }
    },
    fail: err => {
      //android上未初始化蓝牙适配器会走这里
      if (err.errCode === 10000) {
        console.log('android上未初始化蓝牙适配器会走这里')
        _initBluetoothAdapter()
      }
    }
  })

这样可以避免不同页面初始化的问题,当然我没有更新我的工具类,因为使用场景不同,过于复杂的工具类可能更难于理解,如果你在使用的过程中发现无法满足自己的需求,再修改代码
2020/5/14更新,增加了版本号比较的函数
2021/8/3更新,增加初始化蓝牙适配器代码

/**
 *判断蓝牙适配器状态
 */
function _initBleTools() {
	wx.getBluetoothAdapterState({
    success: res => {
      //ios 蓝牙适配器没有初始化会走这里
      if (!res.available) {
        console.log('ios 蓝牙适配器没有初始化会走这里')
        _initBluetoothAdapter()
      } else {
        console.log('蓝牙适配器已初始化 android ios都会走这里')
      }
    },
    fail: err => {
      //android上未初始化蓝牙适配器会走这里
      if (err.errCode === 10000) {
        console.log('android上未初始化蓝牙适配器会走这里')
        _initBluetoothAdapter()
      }
    }
  })
}

/**
 * 初始化蓝牙适配器
 */
function _initBluetoothAdapter(){
	//初始化蓝牙适配器
  wx.openBluetoothAdapter({
    success: function(res) {
      console.log("初始化蓝牙适配器成功")
      //监听蓝牙适配器状态变化事件
      wx.onBluetoothAdapterStateChange(res => {
        if (res.discovering) {
          _this.bleStateListener(constants.STATE_SCANNING)
        } else {
          _this.bleStateListener(constants.STATE_SCANNED)
        }
      })
      //在后面的版本中我发现外部调用没有一个好的位置让调用者能够自动的发起扫描 添加这个方法就是让调用者在初始化适配器之后自动开启扫描
      _this.bleStateListener(constants.STATE_INIT_SUCCESS)
    },
    fail: function(err) {
      //在用户蓝牙开关未开启或者手机不支持蓝牙功能的情况下,调用 wx.openBluetoothAdapter 会返回错误(errCode=10001),表示手机蓝牙功能不可用
      if (err.errCode == 10001) {
        _this.bleStateListener(constants.STATE_CLOSE_BLE)
      }
    }
  })
}

下面是正文

不管你是小程序小白还是ble小白,这个工具类都可以解决你的问题,使用极其简单,改下uuid就可以通信了,下面我简单介绍一下如何调用,不管你是使用我的代码,还是移植到自己的代码中都很简单,源码飞机票 如果帮您解决了燃眉之急请给个star吧…本人在小米,魅族,华为,苹果等机型测试过,都没有问题,为什么要这么封装,因为自己搜到的大部分博客都只是简单的介绍一下官方的文档,要么就是顺带拷贝了一些代码,有源码的呢又和ui等耦合很严重,有很多的Bug,对于小白来说太不友好了,而我这个堪称小白终结者


写在最前:这些是我在准备写和写的过程中的一些需求:

/** 
 * 
 * 只需要最简单的配置 傻瓜式使用 只要通过配置文件修改uuid 即可发送自己的数据至设备 √
 * 兼容ios android  √
 * 对当前用户的手机系统进行判断是否支持ble   √
 *   获取系统  及系统版本  √
 *   获取微信版本   √
 * 判断用户手机蓝牙是否打开  √
 * 错误码定义 √
 * 所有可变的配置抽取出来 统一配置参数  config文件编写√
 * 连接函数需要抽取出来   √
 * 扫描方法抽取 √
 * ble 操作过程中希望所有状态都抽取出来 通过一个函数来分发 而不是在代码中到处修改 √
 * 希望能对ui有最小的侵入 用户可以定义显示的ui 这边只采用最简单的显示在dialog中 √
 * 如果用户的场景不是手动点击连接 而是代码自动进行连接设备 可以调用_connectBle()传入device即可 √
 * 如果用户的场景不需要扫描 则不调用startScanBle()方法即可 这个方法只是断开当前正在连接的设备 开始扫描附近的外围设备 如果对你的逻辑有侵入 请自行修改 √
 * ios扫描同一个设备出现了两个  × 有瑕疵
 * 扫描时间配置  √
 * 将ble所有的操作都抽取为一个js  √
 *  1.之后也可以拷贝到其他地方使用,耦合低
 *  2.如果和业务逻辑都写在一起,代码很乱,阅读性差,不好维护
 *  3.每个用户可能自己的业务逻辑都不同,所以ble部分可能还需要自己再稍加修改,可以更快更容易定位到需要修改的地方
 *  4.更方便测试
 */

写在开始,先看下运行效果:
在这里插入图片描述
再看下工程目录:
在这里插入图片描述


1.如果你是使用我的Demo,那么需要这些配置就可以发送数据了,为了怕有些小白找不到,所以我又粘了图,如果你不知道appid怎么申请,这…

  1. 配置appid 这个使用自己的
  2. 配置uuid ,在constants.js中修改
  3. 配置发送的数据 在constants.js中修改

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

只要在我图示的地方修改uuid为自己的uuid,将数据修改为你的设备能接收的数据就可以了,当然这个步骤是运行我的代码,如果你拷贝我的工具类拿到你i的工程中用,请看下一步


2.如果你是只复制我的工具类的话,utils包必须全部拷贝,当然这些基础的东西就不多赘述了,比如你拷贝到你的项目中那么目录可能和我的不一致,自己改一下即可,这里主要说一下如何调用的我工具类

1.首先你需要在你的实现类中Page中实现这三个方法

  1. writeListener
  2. notifyListener
  3. bleStateListener

下面对三个方法进行说明

writeListener:

 /**
   * 发送数据结果 true or false
   * 如果为false msg是失败原因
   */
  writeListener: function(result, msg) {
    //此处可以执行自己的逻辑 比如一些提示
    console.log(result ? '发送数据成功' : msg)
  },

notifyListener

 /**
   * 接收数据 
   */
  notifyListener: function(data) {
    console.log('接收到数据')
    console.dir(data)
  },

bleStateListener

/**
   * ble状态监听
   */
  bleStateListener: function(state) {
    switch (state) {
      case constants.STATE_DISCONNECTED: //设备连接断开
        console.log('设备连接断开')
        break;
      case constants.STATE_SCANNING: //设备正在扫描
        console.log('设备正在扫描')
        break;
      case constants.STATE_SCANNED: //设备扫描结束
        console.log('设备扫描结束')
        break;
      case constants.STATE_CONNECTING: //设备正在连接
        console.log('设备正在连接')
        break;
      case constants.STATE_CONNECTED: //设备连接成功
        console.log('设备连接成功')
        break;
      case constants.STATE_CONNECTING_ERROR: //连接失败
        console.log('连接失败')
        break;
      case constants.STATE_NOTIFY_SUCCESS: //开启notify成功
        console.log('开启notify成功')
        break;
      case constants.STATE_NOTIFY_FAIL: //开启notify失败
        console.log('开启notify失败')
        break;
      case constants.STATE_CLOSE_BLE: //蓝牙未打开 关闭状态
		 console.log('蓝牙未打开 关闭状态')
        break;
      case constants.STATE_NOTBLE_WCHAT_VERSION: //微信版本过低 不支持ble
 console.log('微信版本过低 不支持ble')
        break;
      case constants.STATE_NOTBLE_SYSTEM_VERSION: //系统版本过低 不支持ble
      console.log('系统版本过低 不支持ble')
        break;
      case constants.STATE_INIT_SUCCESS: //初始化蓝牙适配器成功 
        //tips:可以在此处调用扫描函数 蓝牙适配器初始化成功表示蓝牙在开启状态
        break;
    }
  },

这三个方法理解为回调接口,内部细节可以看我的工具类

上面说了实现这三个方法,下一步就是调用工具类中的方法来完成ble的初始化,扫描等操作,public方法如下:

module.exports = {
  write,//写数据
  startScanBle,//开始扫描
  clear,//退出释放资源
  stopBluetoothDevicesDiscovery,//停止扫描
  connectBle,//连接设备
  initBle,//初始化蓝牙模块
  disconnect//断开连接
}

下面对每个方法进行说明(有执行顺序,并不是绝对顺序,但是你不能先发数据而不扫描设备吧?):
1.initBle:初始化蓝牙适配器,并判断当前手机/微信版本是否支持Ble,调用如下,要放在生命周期函数内执行,结果将通过bleStateListener回调

  onLoad: function() {
    bletools.initBle(this)
  },

注意bletools就是我的工具类,有导包的,这里说一下,下面就不多说了
var bletools = require(’…/…/utils/bletools.js’);
2.startScanBle,扫描附近蓝牙设备

 /**
   * 扫描蓝牙 
   */
  startScanBle {
    bletools.startScanBle({
      success:device => {
      }
    })
  },

返回的device是对象而非数据,对象结构在微信小程序文档中是有的,这里不再赘述,看我的代码是通过数组来存储并显示的,当然你怎么显示或者不显示都可以按照自己的逻辑来

3.stopBluetoothDevicesDiscovery:停止扫描,这个没啥说的,就是停止扫描呗

 bletools.stopBluetoothDevicesDiscovery()

4.connectBle:连接ble设备

 bletools.connectBle(device)

这里接收一个device对象,也就是第2步扫描到的device
5.disconnect:断开当前连接

 bletools.disconnect()

6.write:写数据到设备

  bletools.write(constants.testData1)

constants.testData1是一个16进制数组,这个函数只接收16进制数组,Max长度为20字节
7.clear:释放资源

/**
   * 在页面退出时 销毁蓝牙适配器,在页面销毁的生命周期函数中我们一定要关闭蓝牙适配器释放资源
   */
  onUnload: function() {
    bletools.clear();
  },

上述所有public方法的结果,或者开启的所有监听都会通过上面三个监听函数回调结果出来,比如设备扫描中,连接成功,断开连接,发送数据成功,接受的数据等等等…


如果在使用过程中出现问题,请通过查看日志来解决,在文章的开始有图示一次完整的执行流程,如果发送数据失败,不一定是小程序的问题,请使用排除法来验证换一部手机,如果不是手机的问题请考虑使用第三方的ble工具来验证是否是硬件的问题,本人之前也写过一个Ble指令测试工具,是android的,你可以下载验证一下,博客地址,使用也很简单,下面列出一些可能导致出问题的地方以供排查

  1. uuid不对,这点尤为致命
  2. 连接不上,很大可能是手机兼容性有问题,请换一部手机试试
  3. 扫描不到,请确定硬件Ble不在休眠状态,且在广播状态
  4. 发送数据失败,请检查uuid/数据/ble是否还在连接
  5. 发送数据成功没有收到数据,请检查前面的notify监听已开启,特征变化监听已开启(我这里有log的)

很简单啊 有没有?
如果使用有啥问题,或者有什么bug,请给我留言,谢谢了,最后说下如果帮了你的忙,请给个star

评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值